source('../env.R')
Linking to GEOS 3.11.0, GDAL 3.5.3, PROJ 9.1.0; sf_use_s2() is FALSE
── Attaching core tidyverse packages ─────────────────────────────────────────────────────────────────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ lubridate 1.9.3     ✔ tibble    3.2.1
✔ purrr     1.0.2     ✔ tidyr     1.3.1── Conflicts ───────────────────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter()    masks stats::filter()
✖ dplyr::lag()       masks stats::lag()
✖ lubridate::stamp() masks cowplot::stamp()
ℹ Use the ]8;;http://conflicted.r-lib.org/conflicted package]8;; to force all conflicts to become errors
Attaching package: ‘dbplyr’

The following objects are masked from ‘package:dplyr’:

    ident, sql

Loading required package: ape

Attaching package: ‘ape’

The following object is masked from ‘package:dplyr’:

    where

Loading required package: maps

Attaching package: ‘maps’

The following object is masked from ‘package:purrr’:

    map

Please cite the eBird Status and Trends data using: 
  Fink, D., T. Auer, A. Johnston, M. Strimas-Mackey, S. Ligocki, O. Robinson, 
  W. Hochachka, L. Jaromczyk, C. Crowley, K. Dunham, A. Stillman, I. Davies, 
  A. Rodewald, V. Ruiz-Gutierrez, C. Wood. 2023.
  eBird Status and Trends, Data Version: 2022; Released: 2023. Cornell Lab of
  Ornithology, Ithaca, New York. https://doi.org/10.2173/ebirdst.2022

This version of the package provides access to the 2022 version of the eBird
Status and Trends Data Products. Access to the 2022 data will be provided 
until November 2024 when it will be replaced by the 2023 data. At that 
point, you will be required to update this R package and transition to using 
the new data.
terra 1.7.71

Attaching package: ‘terra’

The following object is masked from ‘package:phytools’:

    rescale

The following objects are masked from ‘package:ape’:

    rotate, trans, zoom

The following object is masked from ‘package:tidyr’:

    extract

Loading required package: permute
Loading required package: lattice
This is vegan 2.6-4

Attaching package: ‘vegan’

The following object is masked from ‘package:phytools’:

    scores

Loading required package: mvtnorm
Loading required package: survival
Loading required package: TH.data
Loading required package: MASS

Attaching package: ‘MASS’

The following object is masked from ‘package:terra’:

    area

The following object is masked from ‘package:dplyr’:

    select


Attaching package: ‘TH.data’

The following object is masked from ‘package:MASS’:

    geyser


Attaching package: ‘ggpubr’

The following object is masked from ‘package:terra’:

    rotate

The following object is masked from ‘package:ape’:

    rotate

The following object is masked from ‘package:cowplot’:

    get_legend

Loading required package: nlme

Attaching package: ‘nlme’

The following object is masked from ‘package:dplyr’:

    collapse

Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2

Attaching package: ‘GGally’

The following object is masked from ‘package:terra’:

    wrap

ggtree v3.11.0 For help: https://yulab-smu.top/treedata-book/

If you use the ggtree package suite in published research, please cite the appropriate paper(s):

Guangchuang Yu, David Smith, Huachen Zhu, Yi Guan, Tommy Tsan-Yuk Lam. ggtree: an R package for visualization and annotation
of phylogenetic trees with their covariates and other associated data. Methods in Ecology and Evolution. 2017, 8(1):28-36.
doi:10.1111/2041-210X.12628

Shuangbin Xu, Lin Li, Xiao Luo, Meijun Chen, Wenli Tang, Li Zhan, Zehan Dai, Tommy T. Lam, Yi Guan, Guangchuang Yu. Ggtree:
A serialized data object for visualization of a phylogenetic tree and annotation data. iMeta 2022, 1(4):e56.
doi:10.1002/imt2.56

LG Wang, TTY Lam, S Xu, Z Dai, L Zhou, T Feng, P Guo, CW Dunn, BR Jones, T Bradley, H Zhu, Y Guan, Y Jiang, G Yu. treeio: an
R package for phylogenetic tree input and output with richly annotated and associated data. Molecular Biology and Evolution.
2020, 37(2):599-603. doi: 10.1093/molbev/msz240 

Attaching package: ‘ggtree’

The following object is masked from ‘package:nlme’:

    collapse

The following object is masked from ‘package:ggpubr’:

    rotate

The following objects are masked from ‘package:terra’:

    flip, inset, rotate

The following object is masked from ‘package:ape’:

    rotate

The following object is masked from ‘package:tidyr’:

    expand


Attaching package: ‘foreach’

The following objects are masked from ‘package:purrr’:

    accumulate, when


Attaching package: ‘scales’

The following object is masked from ‘package:terra’:

    rescale

The following object is masked from ‘package:phytools’:

    rescale

The following object is masked from ‘package:purrr’:

    discard

The following object is masked from ‘package:readr’:

    col_factor
community_data = read_csv(filename(COMMUNITY_OUTPUT_DIR, 'community_assembly_metrics_using_relative_abundance.csv'))
Rows: 341 Columns: 43── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl (43): mntd_normalised, mntd_actual, mntd_min, mntd_max, mntd_mean, mntd_sd, fdiv_normalised, fdiv_actual, fdiv_min, fdiv_max, fdiv_...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(community_data)
colnames(community_data)
 [1] "mntd_normalised"                  "mntd_actual"                      "mntd_min"                        
 [4] "mntd_max"                         "mntd_mean"                        "mntd_sd"                         
 [7] "fdiv_normalised"                  "fdiv_actual"                      "fdiv_min"                        
[10] "fdiv_max"                         "fdiv_mean"                        "fdiv_sd"                         
[13] "mass_fdiv_normalised"             "mass_fdiv_actual"                 "mass_fdiv_min"                   
[16] "mass_fdiv_max"                    "mass_fdiv_mean"                   "mass_fdiv_sd"                    
[19] "locomotory_trait_fdiv_normalised" "locomotory_trait_fdiv_actual"     "locomotory_trait_fdiv_min"       
[22] "locomotory_trait_fdiv_max"        "locomotory_trait_fdiv_mean"       "locomotory_trait_fdiv_sd"        
[25] "trophic_trait_fdiv_normalised"    "trophic_trait_fdiv_actual"        "trophic_trait_fdiv_min"          
[28] "trophic_trait_fdiv_max"           "trophic_trait_fdiv_mean"          "trophic_trait_fdiv_sd"           
[31] "gape_width_fdiv_normalised"       "gape_width_fdiv_actual"           "gape_width_fdiv_min"             
[34] "gape_width_fdiv_max"              "gape_width_fdiv_mean"             "gape_width_fdiv_sd"              
[37] "handwing_index_fdiv_normalised"   "handwing_index_fdiv_actual"       "handwing_index_fdiv_min"         
[40] "handwing_index_fdiv_max"          "handwing_index_fdiv_mean"         "handwing_index_fdiv_sd"          
[43] "city_id"                         

Join on realms

city_to_realm = read_csv(filename(CITY_DATA_OUTPUT_DIR, 'realms.csv'))
Rows: 342 Columns: 2── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): core_realm
dbl (1): city_id
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
community_data_with_realm = left_join(community_data, city_to_realm)
Joining with `by = join_by(city_id)`

Cities as points

city_points = st_centroid(read_sf(filename(CITY_DATA_OUTPUT_DIR, 'city_selection.shp'))) %>% left_join(community_data_with_realm)
Warning: st_centroid assumes attributes are constant over geometriesWarning: st_centroid does not give correct centroids for longitude/latitude dataJoining with `by = join_by(city_id)`
city_points_coords = st_coordinates(city_points)
city_points$latitude = city_points_coords[,1]
city_points$longitude = city_points_coords[,2]
world_map = read_country_boundaries()
Error: Cannot open "/Users/james/Dropbox/PhD/WorldBank_countries_Admin0_10m/WB_countries_Admin0_10m.shp"; The file doesn't seem to exist.

Load community data, and create long format version

communities = read_csv(filename(COMMUNITY_OUTPUT_DIR, 'communities_for_analysis.csv'))
Rows: 2462 Columns: 12── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): city_name, jetz_species_name, seasonal, presence, origin
dbl (4): city_id, distance_to_northern_edge_km, distance_to_southern_edge_km, relative_abundance_proxy
lgl (3): present_urban_high, present_urban_med, present_urban_low
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
communities
community_summary = communities %>% group_by(city_id) %>% summarise(regional_pool_size = n(), urban_pool_size = sum(relative_abundance_proxy > 0))
community_summary

Load trait data

traits = read_csv(filename(TAXONOMY_OUTPUT_DIR, 'traits_jetz.csv'))
Rows: 304 Columns: 6── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): jetz_species_name
dbl (5): gape_width, trophic_trait, locomotory_trait, mass, handwing_index
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(traits)

Load realm geo

resolve = read_resolve()
head(resolve)

Summary metrics by Realm

test_required_values = function(name, df) {
  cat(paste(
    test_value_wilcox(paste(name, 'MNTD'), df$mntd_normalised),
    test_value_wilcox(paste(name, 'Beak Gape FDiv'), df$gape_width_fdiv_normalised),
    test_value_wilcox(paste(name, 'HWI FDiv'), df$handwing_index_fdiv_normalised),
    test_value_wilcox(paste(name, 'Mass FDiv'), df$mass_fdiv_normalised),
    nrow(df),
    sep = "\n"))
}
test_required_values('Global', community_data_with_realm)
Global MNTD median 0.49 
Global Beak Gape FDiv median 0.59 ***
Global HWI FDiv median 0.66 ***
Global Mass FDiv median 0.65 ***
341
unique(community_data_with_realm$core_realm)
[1] "Oceania"     "Nearctic"    "Neotropic"   "Palearctic"  "Afrotropic"  "Indomalayan" "Australasia"
test_required_values('Nearctic', community_data_with_realm[community_data_with_realm$core_realm == 'Nearctic',])
Warning: cannot compute exact p-value with tiesWarning: cannot compute exact p-value with ties
Nearctic MNTD median 0.65 
Nearctic Beak Gape FDiv median 0.63 
Nearctic HWI FDiv median 0.23 **
Nearctic Mass FDiv median 0.48 
66
test_required_values('Neotropic', community_data_with_realm[community_data_with_realm$core_realm == 'Neotropic',])
Neotropic MNTD median 0.53 
Neotropic Beak Gape FDiv median 0.46 
Neotropic HWI FDiv median 0.51 
Neotropic Mass FDiv median 0.65 ***
64
test_required_values('Palearctic', community_data_with_realm[community_data_with_realm$core_realm == 'Palearctic',])
Palearctic MNTD median 0.59 *
Palearctic Beak Gape FDiv median 0.93 ***
Palearctic HWI FDiv median 0.4 
Palearctic Mass FDiv median 0.55 
74
test_required_values('Afrotropic', community_data_with_realm[community_data_with_realm$core_realm == 'Afrotropic',])
Afrotropic MNTD median 0.17 *
Afrotropic Beak Gape FDiv median 0.4 
Afrotropic HWI FDiv median 0.54 
Afrotropic Mass FDiv median 0.34 
9
test_required_values('Indomalayan', community_data_with_realm[community_data_with_realm$core_realm == 'Indomalayan',])
Indomalayan MNTD median 0.43 ***
Indomalayan Beak Gape FDiv median 0.47 
Indomalayan HWI FDiv median 0.88 ***
Indomalayan Mass FDiv median 0.81 ***
121
test_required_values('Australasia', community_data_with_realm[community_data_with_realm$core_realm == 'Australasia',])
Australasia MNTD median 0.53 
Australasia Beak Gape FDiv median 0.46 
Australasia HWI FDiv median 0.79 
Australasia Mass FDiv median 0.55 
6

Summary metrics by introduced species

communities = read_csv(filename(COMMUNITY_OUTPUT_DIR, 'communities_for_analysis.csv'))
Rows: 2462 Columns: 12── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (5): city_name, jetz_species_name, seasonal, presence, origin
dbl (4): city_id, distance_to_northern_edge_km, distance_to_southern_edge_km, relative_abundance_proxy
lgl (3): present_urban_high, present_urban_med, present_urban_low
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
city_introduced_species = communities %>% group_by(city_id) %>% summarise(number_of_species = n()) %>% left_join(
  communities %>% group_by(city_id) %>% filter(origin == 'Introduced') %>% summarise(number_of_introduced_species = n())
) %>% replace_na(list(number_of_introduced_species = 0))
Joining with `by = join_by(city_id)`
community_data_with_introductions = left_join(community_data, city_introduced_species)
Joining with `by = join_by(city_id)`
community_data_with_introductions$has_introduced_species = community_data_with_introductions$number_of_introduced_species > 0
community_data_with_introductions
community_data_with_introductions[,c('mntd_normalised', 'has_introduced_species')]
community_data_with_introductions %>% group_by(has_introduced_species) %>% summarise(
  total_cities = n(), 
  
  mean_mntd_normalised = mean(mntd_normalised, na.rm = T),
  median_mntd_normalised = median(mntd_normalised, na.rm = T),
  sd_mntd_normalised = sd(mntd_normalised, na.rm = T),
  
  mean_mass_fdiv_normalised = mean(mass_fdiv_normalised, na.rm = T),
  median_mass_fdiv_normalised = median(mass_fdiv_normalised, na.rm = T),
  sd_mass_fdiv_normalised = sd(mass_fdiv_normalised, na.rm = T),
  
  mean_gape_width_fdiv_normalised = mean(gape_width_fdiv_normalised, na.rm = T),
  median_gape_width_fdiv_normalised = median(gape_width_fdiv_normalised, na.rm = T),
  sd_gape_width_fdiv_normalised = sd(gape_width_fdiv_normalised, na.rm = T),
  
  mean_handwing_index_fdiv_normalised = mean(handwing_index_fdiv_normalised, na.rm = T),
  median_handwing_index_fdiv_normalised = median(handwing_index_fdiv_normalised, na.rm = T),
  sd_handwing_index_fdiv_normalised = sd(handwing_index_fdiv_normalised, na.rm = T)
)

MNTD

ggplot(community_data_with_introductions, aes(x = has_introduced_species, y = mntd_normalised)) + geom_boxplot()

wilcox.test(mntd_normalised ~ has_introduced_species, community_data_with_introductions, na.action = 'na.omit')

    Wilcoxon rank sum test with continuity correction

data:  mntd_normalised by has_introduced_species
W = 10956, p-value = 0.02272
alternative hypothesis: true location shift is not equal to 0

There is a significant difference between the response of cities with introduced species (0.53±0.27) and those without (0.47±0.19) (p-value = 0.02).

Mass FDiv

ggplot(community_data_with_introductions, aes(x = has_introduced_species, y = mass_fdiv_normalised)) + geom_boxplot()

wilcox.test(mass_fdiv_normalised ~ has_introduced_species, community_data_with_introductions, na.action = 'na.omit')

    Wilcoxon rank sum test with continuity correction

data:  mass_fdiv_normalised by has_introduced_species
W = 17286, p-value = 0.00000004887
alternative hypothesis: true location shift is not equal to 0

There is a significant difference between the response of cities with introduced species (0.57±0.27) and those without (0.73±0.24) (p < 0.0001)

Beak Gape FDiv

ggplot(community_data_with_introductions, aes(x = has_introduced_species, y = gape_width_fdiv_normalised)) + geom_boxplot()

wilcox.test(gape_width_fdiv_normalised ~ has_introduced_species, community_data_with_introductions, na.action = 'na.omit')

    Wilcoxon rank sum test with continuity correction

data:  gape_width_fdiv_normalised by has_introduced_species
W = 10990, p-value = 0.1178
alternative hypothesis: true location shift is not equal to 0

There is NOT a significant difference between the response of cities with introduced species (0.61±0.30) and those without (0.56±0.27)

HWI FDiv

ggplot(community_data_with_introductions, aes(x = has_introduced_species, y = handwing_index_fdiv_normalised)) + geom_boxplot()

wilcox.test(handwing_index_fdiv_normalised ~ has_introduced_species, community_data_with_introductions, na.action = 'na.omit')

    Wilcoxon rank sum test with continuity correction

data:  handwing_index_fdiv_normalised by has_introduced_species
W = 19410, p-value < 0.00000000000000022
alternative hypothesis: true location shift is not equal to 0

There is a significant difference between the response of cities with introduced species (0.49±0.30) and those without (0.79±0.21) (p < 0.0001)

Examine individual metrics

Analysis data frame

geography = read_csv(filename(CITY_DATA_OUTPUT_DIR, 'geography.csv'))
Rows: 342 Columns: 26── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
dbl (26): city_id, city_avg_ndvi, city_avg_elevation, city_avg_temp, city_avg_min_monthly_temp, city_avg_max_monthly_temp, city_avg_mon...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
names(geography)
 [1] "city_id"                       "city_avg_ndvi"                 "city_avg_elevation"            "city_avg_temp"                
 [5] "city_avg_min_monthly_temp"     "city_avg_max_monthly_temp"     "city_avg_monthly_temp"         "city_avg_rainfall"            
 [9] "city_avg_max_monthly_rainfall" "city_avg_min_monthly_rainfall" "city_avg_soil_moisture"        "city_max_elev"                
[13] "city_min_elev"                 "city_elev_range"               "region_20km_avg_ndvi"          "region_20km_avg_elevation"    
[17] "region_20km_avg_soil_moisture" "region_20km_max_elev"          "region_20km_min_elev"          "region_20km_elev_range"       
[21] "region_50km_avg_ndvi"          "region_50km_avg_elevation"     "region_50km_avg_soil_moisture" "region_50km_max_elev"         
[25] "region_50km_min_elev"          "region_50km_elev_range"       
analysis_data = community_data_with_realm[,c('city_id', 'mntd_normalised', 'mass_fdiv_normalised', 'gape_width_fdiv_normalised', 'handwing_index_fdiv_normalised', 'core_realm')] %>% 
  left_join(city_points[,c('city_id', 'latitude', 'longitude')]) %>%
  left_join(community_data_with_introductions[,c('city_id', 'has_introduced_species')]) %>%
  left_join(geography)
Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`Joining with `by = join_by(city_id)`
analysis_data$abs_latitude = abs(analysis_data$latitude)
analysis_data$core_realm = factor(analysis_data$core_realm, levels = c('Palearctic', 'Nearctic', 'Neotropic', 'Afrotropic', 'Indomalayan', 'Australasia', 'Oceania'))
analysis_data$has_introduced_species = factor(analysis_data$has_introduced_species, level = c('TRUE', 'FALSE'), labels = c('Introduced species', 'No introduced species'))
model_data = function(df, dependant_var) {
  df[,c(dependant_var, 'core_realm', 'abs_latitude', 'latitude', 'longitude', 'has_introduced_species', 'city_avg_ndvi', 'city_avg_elevation', 'city_avg_temp', 'city_avg_min_monthly_temp', 'city_avg_max_monthly_temp', 'city_avg_monthly_temp', 'city_avg_rainfall', 'city_avg_max_monthly_rainfall', 'city_avg_min_monthly_rainfall', 'city_avg_soil_moisture', 'city_max_elev', 'city_min_elev', 'city_elev_range', 'region_20km_avg_ndvi', 'region_20km_avg_elevation', 'region_20km_avg_soil_moisture', 'region_20km_max_elev', 'region_20km_min_elev', 'region_20km_elev_range', 'region_50km_avg_ndvi', 'region_50km_avg_elevation', 'region_50km_avg_soil_moisture', 'region_50km_max_elev', 'region_50km_min_elev', 'region_50km_elev_range')]
}
model_data(analysis_data, 'mntd_normalised')
names(analysis_data)
 [1] "city_id"                        "mntd_normalised"                "mass_fdiv_normalised"           "gape_width_fdiv_normalised"    
 [5] "handwing_index_fdiv_normalised" "core_realm"                     "latitude"                       "longitude"                     
 [9] "geometry"                       "has_introduced_species"         "city_avg_ndvi"                  "city_avg_elevation"            
[13] "city_avg_temp"                  "city_avg_min_monthly_temp"      "city_avg_max_monthly_temp"      "city_avg_monthly_temp"         
[17] "city_avg_rainfall"              "city_avg_max_monthly_rainfall"  "city_avg_min_monthly_rainfall"  "city_avg_soil_moisture"        
[21] "city_max_elev"                  "city_min_elev"                  "city_elev_range"                "region_20km_avg_ndvi"          
[25] "region_20km_avg_elevation"      "region_20km_avg_soil_moisture"  "region_20km_max_elev"           "region_20km_min_elev"          
[29] "region_20km_elev_range"         "region_50km_avg_ndvi"           "region_50km_avg_elevation"      "region_50km_avg_soil_moisture" 
[33] "region_50km_max_elev"           "region_50km_min_elev"           "region_50km_elev_range"         "abs_latitude"                  
all_explanatories = c(
    'abs_latitude', 'latitude', 'longitude', 
    'has_introduced_species',
    'city_avg_ndvi', 'city_avg_elevation', 'city_avg_temp', 'city_avg_min_monthly_temp', 'city_avg_max_monthly_temp', 
    'city_avg_monthly_temp', 'city_avg_rainfall', 'city_avg_max_monthly_rainfall', 'city_avg_min_monthly_rainfall', 
    'city_avg_soil_moisture', 'city_max_elev', 'city_min_elev', 'city_elev_range',
    'region_20km_avg_ndvi', 'region_20km_avg_elevation', 'region_20km_avg_soil_moisture', 'region_20km_max_elev', 
    'region_20km_min_elev', 'region_20km_elev_range',
    'region_50km_avg_ndvi', 'region_50km_avg_elevation', 'region_50km_avg_soil_moisture', 'region_50km_max_elev', 
    'region_50km_min_elev', 'region_50km_elev_range',
    'core_realmAfrotropic', 'core_realmAustralasia', 'core_realmIndomalayan', 'core_realmNearctic', 'core_realmNeotropic', 'core_realmPalearctic')

type_labels = function(p) {
  explanatory_levels = all_explanatories[all_explanatories %in% p$explanatory]
  p$explanatory <- factor(p$explanatory, levels = explanatory_levels)
  
  p$type <- 'Realm'
  p$type[p$explanatory %in% c('city_avg_ndvi', 'city_avg_elevation', 'city_avg_temp', 'city_avg_min_monthly_temp', 'city_avg_max_monthly_temp', 
    'city_avg_monthly_temp', 'city_avg_rainfall', 'city_avg_max_monthly_rainfall', 'city_avg_min_monthly_rainfall', 
    'city_avg_soil_moisture', 'city_max_elev', 'city_min_elev', 'city_elev_range')] <- 'City geography'
  p$type[p$explanatory %in% c('region_50km_avg_ndvi', 'region_50km_avg_elevation', 'region_50km_avg_soil_moisture', 'region_50km_max_elev', 
    'region_50km_min_elev', 'region_50km_elev_range')] <- 'Regional (50km) geography'
   p$type[p$explanatory %in% c('region_20km_avg_ndvi', 'region_20km_avg_elevation', 'region_20km_avg_soil_moisture', 'region_20km_max_elev', 
    'region_20km_min_elev', 'region_20km_elev_range')] <- 'Regional (20km) geography'
  p$type[p$explanatory %in% c('abs_latitude', 'latitude', 'longitude')] <- 'Spatial'
  p
}
explanatory_labels = c(
  'has_introduced_species'='Has introduced species', 
  'city_avg_ndvi'='Average NDVI', 
  'city_avg_elevation'='Average elevation', 
  'city_avg_temp'='Average temperature', 
  'city_avg_min_monthly_temp'='Average minimum monthly temperature', 
  'city_avg_max_monthly_temp'='Average maximum monthly temperature', 
  'city_avg_monthly_temp'='Average monthly temperature', 
  'city_avg_rainfall'='Average rainfall', 
  'city_avg_max_monthly_rainfall'='Average maximum monthly rainfall', 
  'city_avg_min_monthly_rainfall'='Average minimum monthly rainfall', 
  'city_avg_soil_moisture'='Average soil moisture', 
  'city_max_elev'='Maximum elevation', 
  'city_min_elev'='Minimum elevation', 
  'city_elev_range'='Elevation range', 
  'region_20km_avg_ndvi'='Average NDVI', 
  'region_20km_avg_elevation'='Average elevation', 
  'region_20km_avg_soil_moisture'='Average soil moisture', 
  'region_20km_max_elev'='Maximum elevation', 
  'region_20km_min_elev'='Minimum elevation',
  'region_20km_elev_range'='Elevation range',
  'region_50km_avg_ndvi'='Average NDVI',
  'region_50km_avg_elevation'='Average elevation',
  'region_50km_avg_soil_moisture'='Average soil moisture', 
  'region_50km_max_elev'='Maximum elevation',
  'region_50km_min_elev'='Minimum elevation', 
  'region_50km_elev_range'='Elevation range',
  'abs_latitude' = 'Absolute latitude',
  'latitude' = 'Latitude',
  'longitude' = 'Longitude',
  'core_realmAfrotropic' = 'Afrotropical', 
  'core_realmAustralasia' = 'Austaliasian', 
  'core_realmIndomalayan' = 'Indomalayan', 
  'core_realmNearctic' = 'Nearctic', 
  'core_realmNeotropic' = 'Neotropical',
  'core_realmPalearctic' = 'Palearctic',
  'core_realmOceania' = 'Oceanical')

Helper plot functions

geom_normalised_histogram = function(name, gg, legend.position = "bottom") {
  gg + 
    geom_histogram(aes(fill = core_realm), binwidth = 0.1, position = "dodge") +
    geom_vline(aes(xintercept = 0.5), color = "#000000", size = 0.4) +
    geom_vline(aes(xintercept = 0), color = "#000000", size = 0.2, linetype = "dashed") +
    geom_vline(aes(xintercept = 1), color = "#000000", size = 0.2, linetype = "dashed") + 
    ylab("Number of cities") + xlab("Normalised Response") + ylim(c(0, 70)) +
    labs(title = name, fill = 'Realm') +
    theme_bw() +
    theme(legend.position=legend.position)
}
geom_map = function(map_sf, title) {
  norm_mntd_analysis_geo = ggplot() + 
    geom_sf(data = world_map, aes(geometry = geometry)) +
    map_sf +
    normalised_colours_scale +
    labs(colour = 'Normalised\nResponse') +
    theme_bw() +
    theme(legend.position="bottom")
}

Helper Dredge functions

# Taken from MuMIN package
# https://rdrr.io/cran/MuMIn/src/R/averaging.R
# https://rdrr.io/cran/MuMIn/src/R/model.avg.R

.coefarr.avg <-
  function(cfarr, weight, revised.var, full, alpha) {   
    weight <- weight / sum(weight)
    nCoef <- dim(cfarr)[3L]
    if(full) {
      nas <- is.na(cfarr[, 1L, ]) & is.na(cfarr[, 2L, ])
      cfarr[, 1L, ][nas] <- cfarr[, 2L, ][nas] <- 0
      #cfarr[, 1L:2L, ][is.na(cfarr[, 1L:2L, ])] <- 0
      if(!all(is.na(cfarr[, 3L, ])))
        cfarr[ ,3L, ][is.na(cfarr[ , 3L, ])] <- Inf
    }
    
    avgcoef <- array(dim = c(nCoef, 5L),
                     dimnames = list(dimnames(cfarr)[[3L]], c("Estimate",
                                                              "Std. Error", "Adjusted SE", "Lower CI", "Upper CI")))
    for(i in seq_len(nCoef))
      avgcoef[i, ] <- par.avg(cfarr[, 1L, i], cfarr[, 2L, i], weight,
                              df = cfarr[, 3L, i], alpha = alpha, revised.var = revised.var)
    
    avgcoef[is.nan(avgcoef)] <- NA
    return(avgcoef)
  }

.makecoefmat <- function(cf) {
  no.ase <- all(is.na(cf[, 3L]))
  z <- abs(cf[, 1L] / cf[, if(no.ase) 2L else 3L])
  pval <- 2 * pnorm(z, lower.tail = FALSE)
  cbind(cf[, if(no.ase) 1L:2L else 1L:3L, drop = FALSE],
        `z value` = z, `Pr(>|z|)` = zapsmall(pval))
}

# Generate model selections using lmer, dredge, and model.avg
# `forumla` : a two-sided linear formula object describing both the fixed-effects and random-effects part of the model
# `data` : the data frame containing the variables from the formula
# `aic_delta` : the AIC delta to use for selecting models in model average
model_average <- function(formula, data, aic_delta = 20) {
  model <- lm(
    formula,
    data=data
  )
  dredge_result <- dredge(model)
  summary(model.avg(dredge_result, subset = delta < aic_delta))
}

# Create a summary data frame containing the selected variables from a model
# `model_sum` : The model summary output from `model_average`
model_summary <- function(model_sum) {
  .column_name <- function(postfix) {
    postfix
  }
  
  # just return the estimate and p value
  weight <- model_sum$msTable[, 5L]
  
  coefmat.full <- as.data.frame(.makecoefmat(.coefarr.avg(model_sum$coefArray, weight,
                                                          attr(model_sum, "revised.var"), TRUE, 0.05)))
  
  coefmat.subset <-
    as.data.frame(.makecoefmat(.coefarr.avg(model_sum$coefArray, weight,
                                            attr(model_sum, "revised.var"), FALSE, 0.05)))
  
  
  coefmat.subset <- coefmat.subset[-c(1), c(1, 2, 5)]
  names(coefmat.subset) <- c(.column_name("estimate"), .column_name("error"), .column_name("p"))
  coefmat.subset <- tibble::rownames_to_column(coefmat.subset, "explanatory")
  coefmat.subset$model = 'subset'
  
  coefmat.full <- coefmat.full[-c(1), c(1, 2, 5)]
  names(coefmat.full) <- c(.column_name("estimate"), .column_name("error"), .column_name("p"))
  coefmat.full <- tibble::rownames_to_column(coefmat.full, "explanatory")
  coefmat.full$model = 'full'
  
  rbind(coefmat.full, coefmat.subset)
}
formula_from_vsurp = function(predictors, dependent, vsurp_result) {
  as.formula(paste(dependent, paste(names(predictors[,vsurp_result$varselect.interp]), collapse="+"), sep = "~"))
}
plot_vsurp_result = function(result_table) {
  plot = result_table[result_table$model == 'full',]
  plot = type_labels(plot)

  ggplot(plot, aes(y=explanatory, x=estimate, colour = type)) + 
    geom_line() +
    geom_point()+
    geom_errorbar(aes(xmin=estimate-error, xmax=estimate+error), width=.2,
                   position=position_dodge(0.05)) +
    scale_y_discrete(
      limits = rev(levels(plot$explanatory)), 
      labels = explanatory_labels) +
    theme_bw() +
    geom_vline(xintercept=0, linetype="dotted") +
    guides(colour=guide_legend(title="Predictor type")) + xlab('Increase from 0 (habitat filtering)\nto 1 (competitive exclusion)\n± Standard Error') + ylab('Predictor') +
    theme(legend.justification = "top")
}

MNTD

norm_mntd_analysis_plot = geom_normalised_histogram(
  'MNTD', 
  ggplot(analysis_data, aes(mntd_normalised))
)
norm_mntd_analysis_plot

norm_mntd_analysis_geo_plot = geom_map(geom_sf(data = analysis_data, aes(color = mntd_normalised, geometry = geometry)), 'MNTD')
norm_mntd_analysis_geo_plot
ggsave(filename(FIGURES_OUTPUT_DIR, 'normalised_mntd_using_abundance.jpg'), width = 2500, height=1100, units = 'px')

norm_mntd_analysis_data = model_data(analysis_data[!is.na(analysis_data$mntd_normalised),], 'mntd_normalised')
norm_mntd_analysis_predictors = norm_mntd_analysis_data[,-1]
norm_mntd_analysis_interp = VSURF(x = norm_mntd_analysis_predictors, y = norm_mntd_analysis_data$mntd_normalised)
Thresholding step
Estimated computational time (on one core): 18 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |======                                                                                                                           |   5%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |===================                                                                                                              |  15%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |================================                                                                                                 |  25%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |=============================================                                                                                    |  35%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |==========================================================                                                                       |  45%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=======================================================================                                                          |  55%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |====================================================================================                                             |  65%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |=================================================================================================                                |  75%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |==============================================================================================================                   |  85%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |===========================================================================================================================      |  95%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Interpretation step (on 29 variables)
Estimated computational time (on one core): between 7 sec. and  31.3 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |====                                                                                                                             |   3%
  |                                                                                                                                       
  |=========                                                                                                                        |   7%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |==================                                                                                                               |  14%
  |                                                                                                                                       
  |======================                                                                                                           |  17%
  |                                                                                                                                       
  |===========================                                                                                                      |  21%
  |                                                                                                                                       
  |===============================                                                                                                  |  24%
  |                                                                                                                                       
  |====================================                                                                                             |  28%
  |                                                                                                                                       
  |========================================                                                                                         |  31%
  |                                                                                                                                       
  |============================================                                                                                     |  34%
  |                                                                                                                                       
  |=================================================                                                                                |  38%
  |                                                                                                                                       
  |=====================================================                                                                            |  41%
  |                                                                                                                                       
  |==========================================================                                                                       |  45%
  |                                                                                                                                       
  |==============================================================                                                                   |  48%
  |                                                                                                                                       
  |===================================================================                                                              |  52%
  |                                                                                                                                       
  |=======================================================================                                                          |  55%
  |                                                                                                                                       
  |============================================================================                                                     |  59%
  |                                                                                                                                       
  |================================================================================                                                 |  62%
  |                                                                                                                                       
  |=====================================================================================                                            |  66%
  |                                                                                                                                       
  |=========================================================================================                                        |  69%
  |                                                                                                                                       
  |=============================================================================================                                    |  72%
  |                                                                                                                                       
  |==================================================================================================                               |  76%
  |                                                                                                                                       
  |======================================================================================================                           |  79%
  |                                                                                                                                       
  |===========================================================================================================                      |  83%
  |                                                                                                                                       
  |===============================================================================================================                  |  86%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |========================================================================================================================         |  93%
  |                                                                                                                                       
  |=============================================================================================================================    |  97%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Prediction step (on 8 variables)
Maximum estimated computational time (on one core): 2.6 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |================                                                                                                                 |  12%
  |                                                                                                                                       
  |================================                                                                                                 |  25%
  |                                                                                                                                       
  |================================================                                                                                 |  38%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=================================================================================                                                |  62%
  |                                                                                                                                       
  |=================================================================================================                                |  75%
  |                                                                                                                                       
  |=================================================================================================================                |  88%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
names(norm_mntd_analysis_predictors[,norm_mntd_analysis_interp$varselect.interp])
[1] "city_avg_monthly_temp"     "city_avg_max_monthly_temp" "core_realm"                "longitude"                
[5] "city_avg_temp"             "latitude"                  "abs_latitude"              "city_avg_min_monthly_temp"
norm_mntd_analysis_formula = formula_from_vsurp(norm_mntd_analysis_predictors, "mntd_normalised", norm_mntd_analysis_interp)
norm_mntd_analysis_result <- model_average(norm_mntd_analysis_formula, norm_mntd_analysis_data)
Fixed term is "(Intercept)"
norm_mntd_analysis_result_table = model_summary(norm_mntd_analysis_result)
norm_mntd_analysis_result_table
norm_mntd_analysis_pred_plot = plot_vsurp_result(norm_mntd_analysis_result_table)
norm_mntd_analysis_pred_plot

Gape width - FDiv

norm_gape_fdiv_analysis_plot = geom_normalised_histogram(
  'Gape FDiv', 
  ggplot(analysis_data, aes(gape_width_fdiv_normalised))
)
norm_gape_fdiv_analysis_plot

norm_gape_fdiv_analysis_geo_plot = geom_map(geom_sf(data = analysis_data, aes(color = gape_width_fdiv_normalised, geometry = geometry)), 'Gape Width FDiv')
norm_gape_fdiv_analysis_geo_plot
ggsave(filename(FIGURES_OUTPUT_DIR, 'normalised_gape_width_using_abundance.jpg'), width = 2500, height=1100, units = 'px')

norm_gape_fdiv_analysis_data = model_data(analysis_data[!is.na(analysis_data$gape_width_fdiv_normalised),], 'gape_width_fdiv_normalised')
norm_gape_fdiv_analysis_predictors = norm_gape_fdiv_analysis_data[,-1]
norm_gape_fdiv_analysis_interp = VSURF(x = norm_gape_fdiv_analysis_predictors, y = norm_gape_fdiv_analysis_data$gape_width_fdiv_normalised)
Thresholding step
Estimated computational time (on one core): 16.1 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |======                                                                                                                           |   5%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |===================                                                                                                              |  15%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |================================                                                                                                 |  25%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |=============================================                                                                                    |  35%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |==========================================================                                                                       |  45%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=======================================================================                                                          |  55%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |====================================================================================                                             |  65%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |=================================================================================================                                |  75%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |==============================================================================================================                   |  85%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |===========================================================================================================================      |  95%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Interpretation step (on 30 variables)
Estimated computational time (on one core): between 6.3 sec. and  33.3 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |====                                                                                                                             |   3%
  |                                                                                                                                       
  |=========                                                                                                                        |   7%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |=================                                                                                                                |  13%
  |                                                                                                                                       
  |======================                                                                                                           |  17%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |==============================                                                                                                   |  23%
  |                                                                                                                                       
  |==================================                                                                                               |  27%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |===========================================                                                                                      |  33%
  |                                                                                                                                       
  |===============================================                                                                                  |  37%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |========================================================                                                                         |  43%
  |                                                                                                                                       
  |============================================================                                                                     |  47%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=====================================================================                                                            |  53%
  |                                                                                                                                       
  |=========================================================================                                                        |  57%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |==================================================================================                                               |  63%
  |                                                                                                                                       
  |======================================================================================                                           |  67%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |===============================================================================================                                  |  73%
  |                                                                                                                                       
  |===================================================================================================                              |  77%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |============================================================================================================                     |  83%
  |                                                                                                                                       
  |================================================================================================================                 |  87%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |========================================================================================================================         |  93%
  |                                                                                                                                       
  |=============================================================================================================================    |  97%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Prediction step (on 11 variables)
Maximum estimated computational time (on one core): 4.5 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |============                                                                                                                     |   9%
  |                                                                                                                                       
  |=======================                                                                                                          |  18%
  |                                                                                                                                       
  |===================================                                                                                              |  27%
  |                                                                                                                                       
  |===============================================                                                                                  |  36%
  |                                                                                                                                       
  |===========================================================                                                                      |  45%
  |                                                                                                                                       
  |======================================================================                                                           |  55%
  |                                                                                                                                       
  |==================================================================================                                               |  64%
  |                                                                                                                                       
  |==============================================================================================                                   |  73%
  |                                                                                                                                       
  |==========================================================================================================                       |  82%
  |                                                                                                                                       
  |=====================================================================================================================            |  91%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
names(norm_gape_fdiv_analysis_predictors[,norm_gape_fdiv_analysis_interp$varselect.interp])
 [1] "longitude"                     "core_realm"                    "abs_latitude"                  "city_avg_max_monthly_temp"    
 [5] "city_avg_temp"                 "city_avg_min_monthly_temp"     "city_avg_max_monthly_rainfall" "city_avg_min_monthly_rainfall"
 [9] "latitude"                      "city_avg_monthly_temp"         "city_max_elev"                
norm_gape_fdiv_analysis_formula = formula_from_vsurp(norm_gape_fdiv_analysis_predictors, "gape_width_fdiv_normalised", norm_gape_fdiv_analysis_interp)
norm_gape_fdiv_analysis_result <- model_average(norm_gape_fdiv_analysis_formula, norm_gape_fdiv_analysis_data)
Fixed term is "(Intercept)"
norm_gape_fdiv_analysis_result_table = model_summary(norm_gape_fdiv_analysis_result)
norm_gape_fdiv_analysis_result_table
norm_gape_fdiv_analysis_pred_plot = plot_vsurp_result(norm_gape_fdiv_analysis_result_table)
norm_gape_fdiv_analysis_pred_plot

HWI - FDiv

norm_hwi_fdiv_loco_analysis_plot = geom_normalised_histogram(
  'HWI FDiv', 
  ggplot(analysis_data, aes(handwing_index_fdiv_normalised))
)
norm_hwi_fdiv_loco_analysis_plot

norm_hwi_fdiv_analysis_geo_plot = geom_map(geom_sf(data = analysis_data, aes(color = handwing_index_fdiv_normalised, geometry = geometry)), 'HWI FDiv')
norm_hwi_fdiv_analysis_geo_plot
ggsave(filename(FIGURES_OUTPUT_DIR, 'normalised_hwi_using_abundance.jpg'), width = 2500, height=1100, units = 'px')

norm_hwi_fdiv_analysis_data = model_data(analysis_data[!is.na(analysis_data$handwing_index_fdiv_normalised),], 'handwing_index_fdiv_normalised')
norm_hwi_fdiv_analysis_predictors = norm_hwi_fdiv_analysis_data[,-1]
norm_hwi_fdiv_analysis_interp = VSURF(x = norm_hwi_fdiv_analysis_predictors, y = norm_hwi_fdiv_analysis_data$handwing_index_fdiv_normalised)
Thresholding step
Estimated computational time (on one core): 14.2 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |======                                                                                                                           |   5%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |===================                                                                                                              |  15%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |================================                                                                                                 |  25%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |=============================================                                                                                    |  35%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |==========================================================                                                                       |  45%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=======================================================================                                                          |  55%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |====================================================================================                                             |  65%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |=================================================================================================                                |  75%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |==============================================================================================================                   |  85%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |===========================================================================================================================      |  95%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Interpretation step (on 30 variables)
Estimated computational time (on one core): between 6 sec. and  29.1 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |====                                                                                                                             |   3%
  |                                                                                                                                       
  |=========                                                                                                                        |   7%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |=================                                                                                                                |  13%
  |                                                                                                                                       
  |======================                                                                                                           |  17%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |==============================                                                                                                   |  23%
  |                                                                                                                                       
  |==================================                                                                                               |  27%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |===========================================                                                                                      |  33%
  |                                                                                                                                       
  |===============================================                                                                                  |  37%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |========================================================                                                                         |  43%
  |                                                                                                                                       
  |============================================================                                                                     |  47%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=====================================================================                                                            |  53%
  |                                                                                                                                       
  |=========================================================================                                                        |  57%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |==================================================================================                                               |  63%
  |                                                                                                                                       
  |======================================================================================                                           |  67%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |===============================================================================================                                  |  73%
  |                                                                                                                                       
  |===================================================================================================                              |  77%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |============================================================================================================                     |  83%
  |                                                                                                                                       
  |================================================================================================================                 |  87%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |========================================================================================================================         |  93%
  |                                                                                                                                       
  |=============================================================================================================================    |  97%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Prediction step (on 8 variables)
Maximum estimated computational time (on one core): 2.3 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |================                                                                                                                 |  12%
  |                                                                                                                                       
  |================================                                                                                                 |  25%
  |                                                                                                                                       
  |================================================                                                                                 |  38%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=================================================================================                                                |  62%
  |                                                                                                                                       
  |=================================================================================================                                |  75%
  |                                                                                                                                       
  |=================================================================================================================                |  88%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
names(norm_hwi_fdiv_analysis_predictors[,norm_hwi_fdiv_analysis_interp$varselect.interp])
[1] "latitude"                      "core_realm"                    "city_avg_max_monthly_temp"     "city_avg_temp"                
[5] "longitude"                     "city_avg_max_monthly_rainfall" "region_50km_elev_range"        "region_50km_min_elev"         
norm_hwi_fdiv_analysis_formula = formula_from_vsurp(norm_hwi_fdiv_analysis_predictors, "handwing_index_fdiv_normalised", norm_hwi_fdiv_analysis_interp)
norm_hwi_fdiv_analysis_result <- model_average(norm_hwi_fdiv_analysis_formula, norm_hwi_fdiv_analysis_data)
Fixed term is "(Intercept)"
norm_hwi_fdiv_analysis_result_table = model_summary(norm_hwi_fdiv_analysis_result)
norm_hwi_fdiv_analysis_result_table
norm_hwi_fdiv_analysis_pred_plot = plot_vsurp_result(norm_hwi_fdiv_analysis_result_table)
norm_hwi_fdiv_analysis_pred_plot

Mass - FDiv

norm_mass_fdiv_loco_analysis_plot = geom_normalised_histogram(
  'Mass FDiv', 
  ggplot(analysis_data, aes(mass_fdiv_normalised))
)
norm_mass_fdiv_loco_analysis_plot

norm_mass_fdiv_analysis_geo_plot = geom_map(geom_sf(data = analysis_data, aes(color = mass_fdiv_normalised, geometry = geometry)), 'Mass FDiv')
norm_mass_fdiv_analysis_geo_plot
ggsave(filename(FIGURES_OUTPUT_DIR, 'normalised_mass_using_abundance.jpg'), width = 2500, height=1100, units = 'px')

norm_mass_fdiv_analysis_data = model_data(analysis_data[!is.na(analysis_data$mass_fdiv_normalised),], 'mass_fdiv_normalised')
norm_mass_fdiv_analysis_predictors = norm_mass_fdiv_analysis_data[,-1]
norm_mass_fdiv_analysis_interp = VSURF(x = norm_mass_fdiv_analysis_predictors, y = norm_mass_fdiv_analysis_data$mass_fdiv_normalised)
Thresholding step
Estimated computational time (on one core): 15.8 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |======                                                                                                                           |   5%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |===================                                                                                                              |  15%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |================================                                                                                                 |  25%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |=============================================                                                                                    |  35%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |==========================================================                                                                       |  45%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=======================================================================                                                          |  55%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |====================================================================================                                             |  65%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |=================================================================================================                                |  75%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |==============================================================================================================                   |  85%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |===========================================================================================================================      |  95%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Interpretation step (on 30 variables)
Estimated computational time (on one core): between 1.5 sec. and  32.4 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |====                                                                                                                             |   3%
  |                                                                                                                                       
  |=========                                                                                                                        |   7%
  |                                                                                                                                       
  |=============                                                                                                                    |  10%
  |                                                                                                                                       
  |=================                                                                                                                |  13%
  |                                                                                                                                       
  |======================                                                                                                           |  17%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |==============================                                                                                                   |  23%
  |                                                                                                                                       
  |==================================                                                                                               |  27%
  |                                                                                                                                       
  |=======================================                                                                                          |  30%
  |                                                                                                                                       
  |===========================================                                                                                      |  33%
  |                                                                                                                                       
  |===============================================                                                                                  |  37%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |========================================================                                                                         |  43%
  |                                                                                                                                       
  |============================================================                                                                     |  47%
  |                                                                                                                                       
  |================================================================                                                                 |  50%
  |                                                                                                                                       
  |=====================================================================                                                            |  53%
  |                                                                                                                                       
  |=========================================================================                                                        |  57%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |==================================================================================                                               |  63%
  |                                                                                                                                       
  |======================================================================================                                           |  67%
  |                                                                                                                                       
  |==========================================================================================                                       |  70%
  |                                                                                                                                       
  |===============================================================================================                                  |  73%
  |                                                                                                                                       
  |===================================================================================================                              |  77%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |============================================================================================================                     |  83%
  |                                                                                                                                       
  |================================================================================================================                 |  87%
  |                                                                                                                                       
  |====================================================================================================================             |  90%
  |                                                                                                                                       
  |========================================================================================================================         |  93%
  |                                                                                                                                       
  |=============================================================================================================================    |  97%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
Prediction step (on 5 variables)
Maximum estimated computational time (on one core): 0.9 sec.

  |                                                                                                                                       
  |                                                                                                                                 |   0%
  |                                                                                                                                       
  |==========================                                                                                                       |  20%
  |                                                                                                                                       
  |====================================================                                                                             |  40%
  |                                                                                                                                       
  |=============================================================================                                                    |  60%
  |                                                                                                                                       
  |=======================================================================================================                          |  80%
  |                                                                                                                                       
  |=================================================================================================================================| 100%
names(norm_mass_fdiv_analysis_predictors[,norm_mass_fdiv_analysis_interp$varselect.interp])
[1] "core_realm"                    "abs_latitude"                  "city_avg_temp"                 "latitude"                     
[5] "city_avg_max_monthly_rainfall"
norm_mass_fdiv_analysis_formula = formula_from_vsurp(norm_mass_fdiv_analysis_predictors, "mass_fdiv_normalised", norm_mass_fdiv_analysis_interp)
norm_mass_fdiv_analysis_result <- model_average(norm_mass_fdiv_analysis_formula, norm_mass_fdiv_analysis_data)
Fixed term is "(Intercept)"
norm_mass_fdiv_analysis_result_table = model_summary(norm_mass_fdiv_analysis_result)
norm_mass_fdiv_analysis_result_table
norm_mass_fdiv_analysis_pred_plot = plot_vsurp_result(norm_mass_fdiv_analysis_result_table)
norm_mass_fdiv_analysis_pred_plot

Create plot of differences in process response

pred_legend <- get_legend(
  # create some space to the left of the legend
  norm_hwi_fdiv_analysis_pred_plot + theme(legend.box.margin = margin(0, 0, 0, 12))
)
Warning: Removed 1 row containing missing values (`geom_line()`).`geom_line()`: Each group consists of only one observation.
ℹ Do you need to adjust the group aesthetic?Warning: Removed 1 rows containing missing values (`geom_point()`).
geo_legend <- get_legend(
  # create some space to the left of the legend
  norm_mass_fdiv_analysis_geo_plot + theme(legend.box.margin = margin(0, 0, 0, 12))
)

plot_grid(
  plot_grid(
    norm_mntd_analysis_geo_plot + theme(legend.position="none"), 
    norm_mntd_analysis_pred_plot + theme(legend.position="none"), 
    nrow = 1
  ) + draw_label("MNTD", size = 16, angle = 90, x = 0.01, y = 0.5),
  plot_grid(
    norm_gape_fdiv_analysis_geo_plot + theme(legend.position="none"), 
    norm_gape_fdiv_analysis_pred_plot + theme(legend.position="none"), 
    nrow = 1
  ) + draw_label("Gape", size = 16, angle = 90, x = 0.01, y = 0.5),
  plot_grid(
    norm_hwi_fdiv_analysis_geo_plot + theme(legend.position="none"), 
    norm_hwi_fdiv_analysis_pred_plot + theme(legend.position="none"), 
    nrow = 1
  ) + draw_label("HWI", size = 16, angle = 90, x = 0.01, y = 0.5),
  plot_grid(
    norm_mass_fdiv_analysis_geo_plot + theme(legend.position="none"), 
    norm_mass_fdiv_analysis_pred_plot + theme(legend.position="none"), 
    nrow = 1
  ) + draw_label("Mass", size = 16, angle = 90, x = 0.01, y = 0.5), 
  plot_grid(
    geo_legend, 
    pred_legend, 
    nrow = 1
  ),
  nrow = 5
)
`geom_line()`: Each group consists of only one observation.
ℹ Do you need to adjust the group aesthetic?`geom_line()`: Each group consists of only one observation.
ℹ Do you need to adjust the group aesthetic?Warning: Removed 1 row containing missing values (`geom_line()`).`geom_line()`: Each group consists of only one observation.
ℹ Do you need to adjust the group aesthetic?Warning: Removed 1 rows containing missing values (`geom_point()`).Warning: Removed 1 row containing missing values (`geom_line()`).`geom_line()`: Each group consists of only one observation.
ℹ Do you need to adjust the group aesthetic?Warning: Removed 1 rows containing missing values (`geom_point()`).

ggsave(filename(FIGURES_OUTPUT_DIR, 'process_response.jpg'), width = 2500, height=5000, units = 'px')

Compare metrics against each other

ggplot(analysis_data, aes(x = gape_width_fdiv_normalised, y = mntd_normalised, colour = core_realm)) + 
  geom_point() +
  ylab("MNTD") + 
  xlab("Gape Width FDiv") +
  theme_bw() + labs(color = "Realm")

ggplot(analysis_data, aes(x = handwing_index_fdiv_normalised, y = mntd_normalised, colour = core_realm)) + 
  geom_point() +
  ylab("MNTD") + 
  xlab("HWI FDiv") +
  theme_bw() + labs(color = "Realm")

ggplot(analysis_data, aes(x = handwing_index_fdiv_normalised, y = gape_width_fdiv_normalised, colour = core_realm)) + 
  geom_point() +
  ylab("Gape Width FDiv") + 
  xlab("HWI FDiv") +
  theme_bw() + labs(color = "Realm")

mntd_fdiv_analysis = analysis_data %>% 
  dplyr::select(city_id,  mntd_normalised, handwing_index_fdiv_normalised, gape_width_fdiv_normalised) %>%
  left_join(community_summary) %>%
  mutate(urban_pool_perc = urban_pool_size * 100 / regional_pool_size)
Joining with `by = join_by(city_id)`
mntd_fdiv_analysis
ggpairs(mntd_fdiv_analysis %>% dplyr::select(mntd_normalised, handwing_index_fdiv_normalised, gape_width_fdiv_normalised, regional_pool_size, urban_pool_size, urban_pool_perc))
ggsave(filename(FIGURES_OUTPUT_DIR, 'appendix_normalised_correlation.jpg'))
Saving 7.29 x 4.51 in image

LS0tCnRpdGxlOiAiTWV0cmljcyBmb3IgYXNzZXNzaW5nIGNvbW11bml0eSBhc3NlbWJseSBwcm9jZXNzZXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawpiaWJsaW9ncmFwaHk6IC4uL3JlZi5iaWIgIAotLS0KCmBgYHtyfQpzb3VyY2UoJy4uL2Vudi5SJykKYGBgCgpgYGB7cn0KY29tbXVuaXR5X2RhdGEgPSByZWFkX2NzdihmaWxlbmFtZShDT01NVU5JVFlfT1VUUFVUX0RJUiwgJ2NvbW11bml0eV9hc3NlbWJseV9tZXRyaWNzX3VzaW5nX3JlbGF0aXZlX2FidW5kYW5jZS5jc3YnKSkKaGVhZChjb21tdW5pdHlfZGF0YSkKY29sbmFtZXMoY29tbXVuaXR5X2RhdGEpCmBgYAoKSm9pbiBvbiByZWFsbXMKYGBge3J9CmNpdHlfdG9fcmVhbG0gPSByZWFkX2NzdihmaWxlbmFtZShDSVRZX0RBVEFfT1VUUFVUX0RJUiwgJ3JlYWxtcy5jc3YnKSkKY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSA9IGxlZnRfam9pbihjb21tdW5pdHlfZGF0YSwgY2l0eV90b19yZWFsbSkKYGBgCgpDaXRpZXMgYXMgcG9pbnRzCmBgYHtyfQpjaXR5X3BvaW50cyA9IHN0X2NlbnRyb2lkKHJlYWRfc2YoZmlsZW5hbWUoQ0lUWV9EQVRBX09VVFBVVF9ESVIsICdjaXR5X3NlbGVjdGlvbi5zaHAnKSkpICU+JSBsZWZ0X2pvaW4oY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSkKY2l0eV9wb2ludHNfY29vcmRzID0gc3RfY29vcmRpbmF0ZXMoY2l0eV9wb2ludHMpCmNpdHlfcG9pbnRzJGxhdGl0dWRlID0gY2l0eV9wb2ludHNfY29vcmRzWywxXQpjaXR5X3BvaW50cyRsb25naXR1ZGUgPSBjaXR5X3BvaW50c19jb29yZHNbLDJdCmBgYAogIApgYGB7cn0Kd29ybGRfbWFwID0gcmVhZF9jb3VudHJ5X2JvdW5kYXJpZXMoKQpgYGAKCkxvYWQgY29tbXVuaXR5IGRhdGEsIGFuZCBjcmVhdGUgbG9uZyBmb3JtYXQgdmVyc2lvbgpgYGB7cn0KY29tbXVuaXRpZXMgPSByZWFkX2NzdihmaWxlbmFtZShDT01NVU5JVFlfT1VUUFVUX0RJUiwgJ2NvbW11bml0aWVzX2Zvcl9hbmFseXNpcy5jc3YnKSkKY29tbXVuaXRpZXMKYGBgCgpgYGB7cn0KY29tbXVuaXR5X3N1bW1hcnkgPSBjb21tdW5pdGllcyAlPiUgZ3JvdXBfYnkoY2l0eV9pZCkgJT4lIHN1bW1hcmlzZShyZWdpb25hbF9wb29sX3NpemUgPSBuKCksIHVyYmFuX3Bvb2xfc2l6ZSA9IHN1bShyZWxhdGl2ZV9hYnVuZGFuY2VfcHJveHkgPiAwKSkKY29tbXVuaXR5X3N1bW1hcnkKYGBgCgpMb2FkIHRyYWl0IGRhdGEKYGBge3J9CnRyYWl0cyA9IHJlYWRfY3N2KGZpbGVuYW1lKFRBWE9OT01ZX09VVFBVVF9ESVIsICd0cmFpdHNfamV0ei5jc3YnKSkKaGVhZCh0cmFpdHMpCmBgYAoKTG9hZCByZWFsbSBnZW8KYGBge3J9CnJlc29sdmUgPSByZWFkX3Jlc29sdmUoKQpoZWFkKHJlc29sdmUpCmBgYAoKIyBTdW1tYXJ5IG1ldHJpY3MgYnkgUmVhbG0KYGBge3J9CnRlc3RfcmVxdWlyZWRfdmFsdWVzID0gZnVuY3Rpb24obmFtZSwgZGYpIHsKICBjYXQocGFzdGUoCiAgICB0ZXN0X3ZhbHVlX3dpbGNveChwYXN0ZShuYW1lLCAnTU5URCcpLCBkZiRtbnRkX25vcm1hbGlzZWQpLAogICAgdGVzdF92YWx1ZV93aWxjb3gocGFzdGUobmFtZSwgJ0JlYWsgR2FwZSBGRGl2JyksIGRmJGdhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkKSwKICAgIHRlc3RfdmFsdWVfd2lsY294KHBhc3RlKG5hbWUsICdIV0kgRkRpdicpLCBkZiRoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQpLAogICAgdGVzdF92YWx1ZV93aWxjb3gocGFzdGUobmFtZSwgJ01hc3MgRkRpdicpLCBkZiRtYXNzX2ZkaXZfbm9ybWFsaXNlZCksCiAgICBucm93KGRmKSwKICAgIHNlcCA9ICJcbiIpKQp9CmBgYAoKYGBge3J9CnRlc3RfcmVxdWlyZWRfdmFsdWVzKCdHbG9iYWwnLCBjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtKQpgYGAKCmBgYHtyfQp1bmlxdWUoY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSRjb3JlX3JlYWxtKQpgYGAKCmBgYHtyfQp0ZXN0X3JlcXVpcmVkX3ZhbHVlcygnTmVhcmN0aWMnLCBjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtW2NvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0kY29yZV9yZWFsbSA9PSAnTmVhcmN0aWMnLF0pCmBgYAoKYGBge3J9CnRlc3RfcmVxdWlyZWRfdmFsdWVzKCdOZW90cm9waWMnLCBjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtW2NvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0kY29yZV9yZWFsbSA9PSAnTmVvdHJvcGljJyxdKQpgYGAKCmBgYHtyfQp0ZXN0X3JlcXVpcmVkX3ZhbHVlcygnUGFsZWFyY3RpYycsIGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG1bY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSRjb3JlX3JlYWxtID09ICdQYWxlYXJjdGljJyxdKQpgYGAKCmBgYHtyfQp0ZXN0X3JlcXVpcmVkX3ZhbHVlcygnQWZyb3Ryb3BpYycsIGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG1bY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSRjb3JlX3JlYWxtID09ICdBZnJvdHJvcGljJyxdKQpgYGAKCmBgYHtyfQp0ZXN0X3JlcXVpcmVkX3ZhbHVlcygnSW5kb21hbGF5YW4nLCBjb21tdW5pdHlfZGF0YV93aXRoX3JlYWxtW2NvbW11bml0eV9kYXRhX3dpdGhfcmVhbG0kY29yZV9yZWFsbSA9PSAnSW5kb21hbGF5YW4nLF0pCmBgYAoKYGBge3J9CnRlc3RfcmVxdWlyZWRfdmFsdWVzKCdBdXN0cmFsYXNpYScsIGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG1bY29tbXVuaXR5X2RhdGFfd2l0aF9yZWFsbSRjb3JlX3JlYWxtID09ICdBdXN0cmFsYXNpYScsXSkKYGBgCgojIFN1bW1hcnkgbWV0cmljcyBieSBpbnRyb2R1Y2VkIHNwZWNpZXMKYGBge3J9CmNvbW11bml0aWVzID0gcmVhZF9jc3YoZmlsZW5hbWUoQ09NTVVOSVRZX09VVFBVVF9ESVIsICdjb21tdW5pdGllc19mb3JfYW5hbHlzaXMuY3N2JykpCmNpdHlfaW50cm9kdWNlZF9zcGVjaWVzID0gY29tbXVuaXRpZXMgJT4lIGdyb3VwX2J5KGNpdHlfaWQpICU+JSBzdW1tYXJpc2UobnVtYmVyX29mX3NwZWNpZXMgPSBuKCkpICU+JSBsZWZ0X2pvaW4oCiAgY29tbXVuaXRpZXMgJT4lIGdyb3VwX2J5KGNpdHlfaWQpICU+JSBmaWx0ZXIob3JpZ2luID09ICdJbnRyb2R1Y2VkJykgJT4lIHN1bW1hcmlzZShudW1iZXJfb2ZfaW50cm9kdWNlZF9zcGVjaWVzID0gbigpKQopICU+JSByZXBsYWNlX25hKGxpc3QobnVtYmVyX29mX2ludHJvZHVjZWRfc3BlY2llcyA9IDApKQoKY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zID0gbGVmdF9qb2luKGNvbW11bml0eV9kYXRhLCBjaXR5X2ludHJvZHVjZWRfc3BlY2llcykKY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zJGhhc19pbnRyb2R1Y2VkX3NwZWNpZXMgPSBjb21tdW5pdHlfZGF0YV93aXRoX2ludHJvZHVjdGlvbnMkbnVtYmVyX29mX2ludHJvZHVjZWRfc3BlY2llcyA+IDAKY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zCmBgYAoKYGBge3J9CmNvbW11bml0eV9kYXRhX3dpdGhfaW50cm9kdWN0aW9uc1ssYygnbW50ZF9ub3JtYWxpc2VkJywgJ2hhc19pbnRyb2R1Y2VkX3NwZWNpZXMnKV0KYGBgCgpgYGB7cn0KY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zICU+JSBncm91cF9ieShoYXNfaW50cm9kdWNlZF9zcGVjaWVzKSAlPiUgc3VtbWFyaXNlKAogIHRvdGFsX2NpdGllcyA9IG4oKSwgCiAgCiAgbWVhbl9tbnRkX25vcm1hbGlzZWQgPSBtZWFuKG1udGRfbm9ybWFsaXNlZCwgbmEucm0gPSBUKSwKICBtZWRpYW5fbW50ZF9ub3JtYWxpc2VkID0gbWVkaWFuKG1udGRfbm9ybWFsaXNlZCwgbmEucm0gPSBUKSwKICBzZF9tbnRkX25vcm1hbGlzZWQgPSBzZChtbnRkX25vcm1hbGlzZWQsIG5hLnJtID0gVCksCiAgCiAgbWVhbl9tYXNzX2ZkaXZfbm9ybWFsaXNlZCA9IG1lYW4obWFzc19mZGl2X25vcm1hbGlzZWQsIG5hLnJtID0gVCksCiAgbWVkaWFuX21hc3NfZmRpdl9ub3JtYWxpc2VkID0gbWVkaWFuKG1hc3NfZmRpdl9ub3JtYWxpc2VkLCBuYS5ybSA9IFQpLAogIHNkX21hc3NfZmRpdl9ub3JtYWxpc2VkID0gc2QobWFzc19mZGl2X25vcm1hbGlzZWQsIG5hLnJtID0gVCksCiAgCiAgbWVhbl9nYXBlX3dpZHRoX2ZkaXZfbm9ybWFsaXNlZCA9IG1lYW4oZ2FwZV93aWR0aF9mZGl2X25vcm1hbGlzZWQsIG5hLnJtID0gVCksCiAgbWVkaWFuX2dhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkID0gbWVkaWFuKGdhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkLCBuYS5ybSA9IFQpLAogIHNkX2dhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkID0gc2QoZ2FwZV93aWR0aF9mZGl2X25vcm1hbGlzZWQsIG5hLnJtID0gVCksCiAgCiAgbWVhbl9oYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQgPSBtZWFuKGhhbmR3aW5nX2luZGV4X2ZkaXZfbm9ybWFsaXNlZCwgbmEucm0gPSBUKSwKICBtZWRpYW5faGFuZHdpbmdfaW5kZXhfZmRpdl9ub3JtYWxpc2VkID0gbWVkaWFuKGhhbmR3aW5nX2luZGV4X2ZkaXZfbm9ybWFsaXNlZCwgbmEucm0gPSBUKSwKICBzZF9oYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQgPSBzZChoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQsIG5hLnJtID0gVCkKKQpgYGAKCiMjIE1OVEQKYGBge3J9CmdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX2ludHJvZHVjdGlvbnMsIGFlcyh4ID0gaGFzX2ludHJvZHVjZWRfc3BlY2llcywgeSA9IG1udGRfbm9ybWFsaXNlZCkpICsgZ2VvbV9ib3hwbG90KCkKYGBgCgpgYGB7cn0Kd2lsY294LnRlc3QobW50ZF9ub3JtYWxpc2VkIH4gaGFzX2ludHJvZHVjZWRfc3BlY2llcywgY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zLCBuYS5hY3Rpb24gPSAnbmEub21pdCcpCmBgYAoKVGhlcmUgaXMgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHJlc3BvbnNlIG9mIGNpdGllcyB3aXRoIGludHJvZHVjZWQgc3BlY2llcyAoMC41M8KxMC4yNykgYW5kIHRob3NlIHdpdGhvdXQgKDAuNDfCsTAuMTkpIChwLXZhbHVlID0gMC4wMikuCgoKIyMgTWFzcyBGRGl2CmBgYHtyfQpnZ3Bsb3QoY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zLCBhZXMoeCA9IGhhc19pbnRyb2R1Y2VkX3NwZWNpZXMsIHkgPSBtYXNzX2ZkaXZfbm9ybWFsaXNlZCkpICsgZ2VvbV9ib3hwbG90KCkKYGBgCgpgYGB7cn0Kd2lsY294LnRlc3QobWFzc19mZGl2X25vcm1hbGlzZWQgfiBoYXNfaW50cm9kdWNlZF9zcGVjaWVzLCBjb21tdW5pdHlfZGF0YV93aXRoX2ludHJvZHVjdGlvbnMsIG5hLmFjdGlvbiA9ICduYS5vbWl0JykKYGBgClRoZXJlIGlzIGEgc2lnbmlmaWNhbnQgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSByZXNwb25zZSBvZiBjaXRpZXMgd2l0aCBpbnRyb2R1Y2VkIHNwZWNpZXMgKDAuNTfCsTAuMjcpIGFuZCB0aG9zZSB3aXRob3V0ICgwLjczwrEwLjI0KSAocCA8IDAuMDAwMSkKCgojIyBCZWFrIEdhcGUgRkRpdgpgYGB7cn0KZ2dwbG90KGNvbW11bml0eV9kYXRhX3dpdGhfaW50cm9kdWN0aW9ucywgYWVzKHggPSBoYXNfaW50cm9kdWNlZF9zcGVjaWVzLCB5ID0gZ2FwZV93aWR0aF9mZGl2X25vcm1hbGlzZWQpKSArIGdlb21fYm94cGxvdCgpCmBgYAoKYGBge3J9CndpbGNveC50ZXN0KGdhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkIH4gaGFzX2ludHJvZHVjZWRfc3BlY2llcywgY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zLCBuYS5hY3Rpb24gPSAnbmEub21pdCcpCmBgYApUaGVyZSBpcyBOT1QgYSBzaWduaWZpY2FudCBkaWZmZXJlbmNlIGJldHdlZW4gdGhlIHJlc3BvbnNlIG9mIGNpdGllcyB3aXRoIGludHJvZHVjZWQgc3BlY2llcyAoMC42McKxMC4zMCkgYW5kIHRob3NlIHdpdGhvdXQgKDAuNTbCsTAuMjcpCgoKIyMgSFdJIEZEaXYKYGBge3J9CmdncGxvdChjb21tdW5pdHlfZGF0YV93aXRoX2ludHJvZHVjdGlvbnMsIGFlcyh4ID0gaGFzX2ludHJvZHVjZWRfc3BlY2llcywgeSA9IGhhbmR3aW5nX2luZGV4X2ZkaXZfbm9ybWFsaXNlZCkpICsgZ2VvbV9ib3hwbG90KCkKYGBgCgpgYGB7cn0Kd2lsY294LnRlc3QoaGFuZHdpbmdfaW5kZXhfZmRpdl9ub3JtYWxpc2VkIH4gaGFzX2ludHJvZHVjZWRfc3BlY2llcywgY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zLCBuYS5hY3Rpb24gPSAnbmEub21pdCcpCmBgYApUaGVyZSBpcyBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgcmVzcG9uc2Ugb2YgY2l0aWVzIHdpdGggaW50cm9kdWNlZCBzcGVjaWVzICgwLjQ5wrEwLjMwKSBhbmQgdGhvc2Ugd2l0aG91dCAoMC43OcKxMC4yMSkgKHAgPCAwLjAwMDEpCgoKIyBFeGFtaW5lIGluZGl2aWR1YWwgbWV0cmljcwoKIyMgQW5hbHlzaXMgZGF0YSBmcmFtZQpgYGB7cn0KZ2VvZ3JhcGh5ID0gcmVhZF9jc3YoZmlsZW5hbWUoQ0lUWV9EQVRBX09VVFBVVF9ESVIsICdnZW9ncmFwaHkuY3N2JykpCm5hbWVzKGdlb2dyYXBoeSkKYGBgCgpgYGB7cn0KYW5hbHlzaXNfZGF0YSA9IGNvbW11bml0eV9kYXRhX3dpdGhfcmVhbG1bLGMoJ2NpdHlfaWQnLCAnbW50ZF9ub3JtYWxpc2VkJywgJ21hc3NfZmRpdl9ub3JtYWxpc2VkJywgJ2dhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkJywgJ2hhbmR3aW5nX2luZGV4X2ZkaXZfbm9ybWFsaXNlZCcsICdjb3JlX3JlYWxtJyldICU+JSAKICBsZWZ0X2pvaW4oY2l0eV9wb2ludHNbLGMoJ2NpdHlfaWQnLCAnbGF0aXR1ZGUnLCAnbG9uZ2l0dWRlJyldKSAlPiUKICBsZWZ0X2pvaW4oY29tbXVuaXR5X2RhdGFfd2l0aF9pbnRyb2R1Y3Rpb25zWyxjKCdjaXR5X2lkJywgJ2hhc19pbnRyb2R1Y2VkX3NwZWNpZXMnKV0pICU+JQogIGxlZnRfam9pbihnZW9ncmFwaHkpCgphbmFseXNpc19kYXRhJGFic19sYXRpdHVkZSA9IGFicyhhbmFseXNpc19kYXRhJGxhdGl0dWRlKQphbmFseXNpc19kYXRhJGNvcmVfcmVhbG0gPSBmYWN0b3IoYW5hbHlzaXNfZGF0YSRjb3JlX3JlYWxtLCBsZXZlbHMgPSBjKCdQYWxlYXJjdGljJywgJ05lYXJjdGljJywgJ05lb3Ryb3BpYycsICdBZnJvdHJvcGljJywgJ0luZG9tYWxheWFuJywgJ0F1c3RyYWxhc2lhJywgJ09jZWFuaWEnKSkKYW5hbHlzaXNfZGF0YSRoYXNfaW50cm9kdWNlZF9zcGVjaWVzID0gZmFjdG9yKGFuYWx5c2lzX2RhdGEkaGFzX2ludHJvZHVjZWRfc3BlY2llcywgbGV2ZWwgPSBjKCdUUlVFJywgJ0ZBTFNFJyksIGxhYmVscyA9IGMoJ0ludHJvZHVjZWQgc3BlY2llcycsICdObyBpbnRyb2R1Y2VkIHNwZWNpZXMnKSkKYGBgCgpgYGB7cn0KbW9kZWxfZGF0YSA9IGZ1bmN0aW9uKGRmLCBkZXBlbmRhbnRfdmFyKSB7CiAgZGZbLGMoZGVwZW5kYW50X3ZhciwgJ2NvcmVfcmVhbG0nLCAnYWJzX2xhdGl0dWRlJywgJ2xhdGl0dWRlJywgJ2xvbmdpdHVkZScsICdoYXNfaW50cm9kdWNlZF9zcGVjaWVzJywgJ2NpdHlfYXZnX25kdmknLCAnY2l0eV9hdmdfZWxldmF0aW9uJywgJ2NpdHlfYXZnX3RlbXAnLCAnY2l0eV9hdmdfbWluX21vbnRobHlfdGVtcCcsICdjaXR5X2F2Z19tYXhfbW9udGhseV90ZW1wJywgJ2NpdHlfYXZnX21vbnRobHlfdGVtcCcsICdjaXR5X2F2Z19yYWluZmFsbCcsICdjaXR5X2F2Z19tYXhfbW9udGhseV9yYWluZmFsbCcsICdjaXR5X2F2Z19taW5fbW9udGhseV9yYWluZmFsbCcsICdjaXR5X2F2Z19zb2lsX21vaXN0dXJlJywgJ2NpdHlfbWF4X2VsZXYnLCAnY2l0eV9taW5fZWxldicsICdjaXR5X2VsZXZfcmFuZ2UnLCAncmVnaW9uXzIwa21fYXZnX25kdmknLCAncmVnaW9uXzIwa21fYXZnX2VsZXZhdGlvbicsICdyZWdpb25fMjBrbV9hdmdfc29pbF9tb2lzdHVyZScsICdyZWdpb25fMjBrbV9tYXhfZWxldicsICdyZWdpb25fMjBrbV9taW5fZWxldicsICdyZWdpb25fMjBrbV9lbGV2X3JhbmdlJywgJ3JlZ2lvbl81MGttX2F2Z19uZHZpJywgJ3JlZ2lvbl81MGttX2F2Z19lbGV2YXRpb24nLCAncmVnaW9uXzUwa21fYXZnX3NvaWxfbW9pc3R1cmUnLCAncmVnaW9uXzUwa21fbWF4X2VsZXYnLCAncmVnaW9uXzUwa21fbWluX2VsZXYnLCAncmVnaW9uXzUwa21fZWxldl9yYW5nZScpXQp9Cm1vZGVsX2RhdGEoYW5hbHlzaXNfZGF0YSwgJ21udGRfbm9ybWFsaXNlZCcpCmBgYAoKYGBge3J9Cm5hbWVzKGFuYWx5c2lzX2RhdGEpCmBgYAoKYGBge3J9CmFsbF9leHBsYW5hdG9yaWVzID0gYygKICAgICdhYnNfbGF0aXR1ZGUnLCAnbGF0aXR1ZGUnLCAnbG9uZ2l0dWRlJywgCiAgICAnaGFzX2ludHJvZHVjZWRfc3BlY2llcycsCiAgICAnY2l0eV9hdmdfbmR2aScsICdjaXR5X2F2Z19lbGV2YXRpb24nLCAnY2l0eV9hdmdfdGVtcCcsICdjaXR5X2F2Z19taW5fbW9udGhseV90ZW1wJywgJ2NpdHlfYXZnX21heF9tb250aGx5X3RlbXAnLCAKICAgICdjaXR5X2F2Z19tb250aGx5X3RlbXAnLCAnY2l0eV9hdmdfcmFpbmZhbGwnLCAnY2l0eV9hdmdfbWF4X21vbnRobHlfcmFpbmZhbGwnLCAnY2l0eV9hdmdfbWluX21vbnRobHlfcmFpbmZhbGwnLCAKICAgICdjaXR5X2F2Z19zb2lsX21vaXN0dXJlJywgJ2NpdHlfbWF4X2VsZXYnLCAnY2l0eV9taW5fZWxldicsICdjaXR5X2VsZXZfcmFuZ2UnLAogICAgJ3JlZ2lvbl8yMGttX2F2Z19uZHZpJywgJ3JlZ2lvbl8yMGttX2F2Z19lbGV2YXRpb24nLCAncmVnaW9uXzIwa21fYXZnX3NvaWxfbW9pc3R1cmUnLCAncmVnaW9uXzIwa21fbWF4X2VsZXYnLCAKICAgICdyZWdpb25fMjBrbV9taW5fZWxldicsICdyZWdpb25fMjBrbV9lbGV2X3JhbmdlJywKICAgICdyZWdpb25fNTBrbV9hdmdfbmR2aScsICdyZWdpb25fNTBrbV9hdmdfZWxldmF0aW9uJywgJ3JlZ2lvbl81MGttX2F2Z19zb2lsX21vaXN0dXJlJywgJ3JlZ2lvbl81MGttX21heF9lbGV2JywgCiAgICAncmVnaW9uXzUwa21fbWluX2VsZXYnLCAncmVnaW9uXzUwa21fZWxldl9yYW5nZScsCiAgICAnY29yZV9yZWFsbUFmcm90cm9waWMnLCAnY29yZV9yZWFsbUF1c3RyYWxhc2lhJywgJ2NvcmVfcmVhbG1JbmRvbWFsYXlhbicsICdjb3JlX3JlYWxtTmVhcmN0aWMnLCAnY29yZV9yZWFsbU5lb3Ryb3BpYycsICdjb3JlX3JlYWxtUGFsZWFyY3RpYycpCgp0eXBlX2xhYmVscyA9IGZ1bmN0aW9uKHApIHsKICBleHBsYW5hdG9yeV9sZXZlbHMgPSBhbGxfZXhwbGFuYXRvcmllc1thbGxfZXhwbGFuYXRvcmllcyAlaW4lIHAkZXhwbGFuYXRvcnldCiAgcCRleHBsYW5hdG9yeSA8LSBmYWN0b3IocCRleHBsYW5hdG9yeSwgbGV2ZWxzID0gZXhwbGFuYXRvcnlfbGV2ZWxzKQogIAogIHAkdHlwZSA8LSAnUmVhbG0nCiAgcCR0eXBlW3AkZXhwbGFuYXRvcnkgJWluJSBjKCdjaXR5X2F2Z19uZHZpJywgJ2NpdHlfYXZnX2VsZXZhdGlvbicsICdjaXR5X2F2Z190ZW1wJywgJ2NpdHlfYXZnX21pbl9tb250aGx5X3RlbXAnLCAnY2l0eV9hdmdfbWF4X21vbnRobHlfdGVtcCcsIAogICAgJ2NpdHlfYXZnX21vbnRobHlfdGVtcCcsICdjaXR5X2F2Z19yYWluZmFsbCcsICdjaXR5X2F2Z19tYXhfbW9udGhseV9yYWluZmFsbCcsICdjaXR5X2F2Z19taW5fbW9udGhseV9yYWluZmFsbCcsIAogICAgJ2NpdHlfYXZnX3NvaWxfbW9pc3R1cmUnLCAnY2l0eV9tYXhfZWxldicsICdjaXR5X21pbl9lbGV2JywgJ2NpdHlfZWxldl9yYW5nZScpXSA8LSAnQ2l0eSBnZW9ncmFwaHknCiAgcCR0eXBlW3AkZXhwbGFuYXRvcnkgJWluJSBjKCdyZWdpb25fNTBrbV9hdmdfbmR2aScsICdyZWdpb25fNTBrbV9hdmdfZWxldmF0aW9uJywgJ3JlZ2lvbl81MGttX2F2Z19zb2lsX21vaXN0dXJlJywgJ3JlZ2lvbl81MGttX21heF9lbGV2JywgCiAgICAncmVnaW9uXzUwa21fbWluX2VsZXYnLCAncmVnaW9uXzUwa21fZWxldl9yYW5nZScpXSA8LSAnUmVnaW9uYWwgKDUwa20pIGdlb2dyYXBoeScKICAgcCR0eXBlW3AkZXhwbGFuYXRvcnkgJWluJSBjKCdyZWdpb25fMjBrbV9hdmdfbmR2aScsICdyZWdpb25fMjBrbV9hdmdfZWxldmF0aW9uJywgJ3JlZ2lvbl8yMGttX2F2Z19zb2lsX21vaXN0dXJlJywgJ3JlZ2lvbl8yMGttX21heF9lbGV2JywgCiAgICAncmVnaW9uXzIwa21fbWluX2VsZXYnLCAncmVnaW9uXzIwa21fZWxldl9yYW5nZScpXSA8LSAnUmVnaW9uYWwgKDIwa20pIGdlb2dyYXBoeScKICBwJHR5cGVbcCRleHBsYW5hdG9yeSAlaW4lIGMoJ2Fic19sYXRpdHVkZScsICdsYXRpdHVkZScsICdsb25naXR1ZGUnKV0gPC0gJ1NwYXRpYWwnCiAgcAp9CmBgYAoKYGBge3J9CmV4cGxhbmF0b3J5X2xhYmVscyA9IGMoCiAgJ2hhc19pbnRyb2R1Y2VkX3NwZWNpZXMnPSdIYXMgaW50cm9kdWNlZCBzcGVjaWVzJywgCiAgJ2NpdHlfYXZnX25kdmknPSdBdmVyYWdlIE5EVkknLCAKICAnY2l0eV9hdmdfZWxldmF0aW9uJz0nQXZlcmFnZSBlbGV2YXRpb24nLCAKICAnY2l0eV9hdmdfdGVtcCc9J0F2ZXJhZ2UgdGVtcGVyYXR1cmUnLCAKICAnY2l0eV9hdmdfbWluX21vbnRobHlfdGVtcCc9J0F2ZXJhZ2UgbWluaW11bSBtb250aGx5IHRlbXBlcmF0dXJlJywgCiAgJ2NpdHlfYXZnX21heF9tb250aGx5X3RlbXAnPSdBdmVyYWdlIG1heGltdW0gbW9udGhseSB0ZW1wZXJhdHVyZScsIAogICdjaXR5X2F2Z19tb250aGx5X3RlbXAnPSdBdmVyYWdlIG1vbnRobHkgdGVtcGVyYXR1cmUnLCAKICAnY2l0eV9hdmdfcmFpbmZhbGwnPSdBdmVyYWdlIHJhaW5mYWxsJywgCiAgJ2NpdHlfYXZnX21heF9tb250aGx5X3JhaW5mYWxsJz0nQXZlcmFnZSBtYXhpbXVtIG1vbnRobHkgcmFpbmZhbGwnLCAKICAnY2l0eV9hdmdfbWluX21vbnRobHlfcmFpbmZhbGwnPSdBdmVyYWdlIG1pbmltdW0gbW9udGhseSByYWluZmFsbCcsIAogICdjaXR5X2F2Z19zb2lsX21vaXN0dXJlJz0nQXZlcmFnZSBzb2lsIG1vaXN0dXJlJywgCiAgJ2NpdHlfbWF4X2VsZXYnPSdNYXhpbXVtIGVsZXZhdGlvbicsIAogICdjaXR5X21pbl9lbGV2Jz0nTWluaW11bSBlbGV2YXRpb24nLCAKICAnY2l0eV9lbGV2X3JhbmdlJz0nRWxldmF0aW9uIHJhbmdlJywgCiAgJ3JlZ2lvbl8yMGttX2F2Z19uZHZpJz0nQXZlcmFnZSBORFZJJywgCiAgJ3JlZ2lvbl8yMGttX2F2Z19lbGV2YXRpb24nPSdBdmVyYWdlIGVsZXZhdGlvbicsIAogICdyZWdpb25fMjBrbV9hdmdfc29pbF9tb2lzdHVyZSc9J0F2ZXJhZ2Ugc29pbCBtb2lzdHVyZScsIAogICdyZWdpb25fMjBrbV9tYXhfZWxldic9J01heGltdW0gZWxldmF0aW9uJywgCiAgJ3JlZ2lvbl8yMGttX21pbl9lbGV2Jz0nTWluaW11bSBlbGV2YXRpb24nLAogICdyZWdpb25fMjBrbV9lbGV2X3JhbmdlJz0nRWxldmF0aW9uIHJhbmdlJywKICAncmVnaW9uXzUwa21fYXZnX25kdmknPSdBdmVyYWdlIE5EVkknLAogICdyZWdpb25fNTBrbV9hdmdfZWxldmF0aW9uJz0nQXZlcmFnZSBlbGV2YXRpb24nLAogICdyZWdpb25fNTBrbV9hdmdfc29pbF9tb2lzdHVyZSc9J0F2ZXJhZ2Ugc29pbCBtb2lzdHVyZScsIAogICdyZWdpb25fNTBrbV9tYXhfZWxldic9J01heGltdW0gZWxldmF0aW9uJywKICAncmVnaW9uXzUwa21fbWluX2VsZXYnPSdNaW5pbXVtIGVsZXZhdGlvbicsIAogICdyZWdpb25fNTBrbV9lbGV2X3JhbmdlJz0nRWxldmF0aW9uIHJhbmdlJywKICAnYWJzX2xhdGl0dWRlJyA9ICdBYnNvbHV0ZSBsYXRpdHVkZScsCiAgJ2xhdGl0dWRlJyA9ICdMYXRpdHVkZScsCiAgJ2xvbmdpdHVkZScgPSAnTG9uZ2l0dWRlJywKICAnY29yZV9yZWFsbUFmcm90cm9waWMnID0gJ0Fmcm90cm9waWNhbCcsIAogICdjb3JlX3JlYWxtQXVzdHJhbGFzaWEnID0gJ0F1c3RhbGlhc2lhbicsIAogICdjb3JlX3JlYWxtSW5kb21hbGF5YW4nID0gJ0luZG9tYWxheWFuJywgCiAgJ2NvcmVfcmVhbG1OZWFyY3RpYycgPSAnTmVhcmN0aWMnLCAKICAnY29yZV9yZWFsbU5lb3Ryb3BpYycgPSAnTmVvdHJvcGljYWwnLAogICdjb3JlX3JlYWxtUGFsZWFyY3RpYycgPSAnUGFsZWFyY3RpYycsCiAgJ2NvcmVfcmVhbG1PY2VhbmlhJyA9ICdPY2VhbmljYWwnKQpgYGAKCiMjIEhlbHBlciBwbG90IGZ1bmN0aW9ucwpgYGB7cn0KZ2VvbV9ub3JtYWxpc2VkX2hpc3RvZ3JhbSA9IGZ1bmN0aW9uKG5hbWUsIGdnLCBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgewogIGdnICsgCiAgICBnZW9tX2hpc3RvZ3JhbShhZXMoZmlsbCA9IGNvcmVfcmVhbG0pLCBiaW53aWR0aCA9IDAuMSwgcG9zaXRpb24gPSAiZG9kZ2UiKSArCiAgICBnZW9tX3ZsaW5lKGFlcyh4aW50ZXJjZXB0ID0gMC41KSwgY29sb3IgPSAiIzAwMDAwMCIsIHNpemUgPSAwLjQpICsKICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAwKSwgY29sb3IgPSAiIzAwMDAwMCIsIHNpemUgPSAwLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsKICAgIGdlb21fdmxpbmUoYWVzKHhpbnRlcmNlcHQgPSAxKSwgY29sb3IgPSAiIzAwMDAwMCIsIHNpemUgPSAwLjIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsgCiAgICB5bGFiKCJOdW1iZXIgb2YgY2l0aWVzIikgKyB4bGFiKCJOb3JtYWxpc2VkIFJlc3BvbnNlIikgKyB5bGltKGMoMCwgNzApKSArCiAgICBsYWJzKHRpdGxlID0gbmFtZSwgZmlsbCA9ICdSZWFsbScpICsKICAgIHRoZW1lX2J3KCkgKwogICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPWxlZ2VuZC5wb3NpdGlvbikKfQpgYGAKCmBgYHtyfQpnZW9tX21hcCA9IGZ1bmN0aW9uKG1hcF9zZiwgdGl0bGUpIHsKICBub3JtX21udGRfYW5hbHlzaXNfZ2VvID0gZ2dwbG90KCkgKyAKICAgIGdlb21fc2YoZGF0YSA9IHdvcmxkX21hcCwgYWVzKGdlb21ldHJ5ID0gZ2VvbWV0cnkpKSArCiAgICBtYXBfc2YgKwogICAgbm9ybWFsaXNlZF9jb2xvdXJzX3NjYWxlICsKICAgIGxhYnMoY29sb3VyID0gJ05vcm1hbGlzZWRcblJlc3BvbnNlJykgKwogICAgdGhlbWVfYncoKSArCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImJvdHRvbSIpCn0KYGBgCgojIyBIZWxwZXIgRHJlZGdlIGZ1bmN0aW9ucwpgYGB7cn0KIyBUYWtlbiBmcm9tIE11TUlOIHBhY2thZ2UKIyBodHRwczovL3JkcnIuaW8vY3Jhbi9NdU1Jbi9zcmMvUi9hdmVyYWdpbmcuUgojIGh0dHBzOi8vcmRyci5pby9jcmFuL011TUluL3NyYy9SL21vZGVsLmF2Zy5SCgouY29lZmFyci5hdmcgPC0KICBmdW5jdGlvbihjZmFyciwgd2VpZ2h0LCByZXZpc2VkLnZhciwgZnVsbCwgYWxwaGEpIHsJCiAgICB3ZWlnaHQgPC0gd2VpZ2h0IC8gc3VtKHdlaWdodCkKICAgIG5Db2VmIDwtIGRpbShjZmFycilbM0xdCiAgICBpZihmdWxsKSB7CiAgICAgIG5hcyA8LSBpcy5uYShjZmFyclssIDFMLCBdKSAmIGlzLm5hKGNmYXJyWywgMkwsIF0pCiAgICAgIGNmYXJyWywgMUwsIF1bbmFzXSA8LSBjZmFyclssIDJMLCBdW25hc10gPC0gMAogICAgICAjY2ZhcnJbLCAxTDoyTCwgXVtpcy5uYShjZmFyclssIDFMOjJMLCBdKV0gPC0gMAogICAgICBpZighYWxsKGlzLm5hKGNmYXJyWywgM0wsIF0pKSkKICAgICAgICBjZmFyclsgLDNMLCBdW2lzLm5hKGNmYXJyWyAsIDNMLCBdKV0gPC0gSW5mCiAgICB9CiAgICAKICAgIGF2Z2NvZWYgPC0gYXJyYXkoZGltID0gYyhuQ29lZiwgNUwpLAogICAgICAgICAgICAgICAgICAgICBkaW1uYW1lcyA9IGxpc3QoZGltbmFtZXMoY2ZhcnIpW1szTF1dLCBjKCJFc3RpbWF0ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlN0ZC4gRXJyb3IiLCAiQWRqdXN0ZWQgU0UiLCAiTG93ZXIgQ0kiLCAiVXBwZXIgQ0kiKSkpCiAgICBmb3IoaSBpbiBzZXFfbGVuKG5Db2VmKSkKICAgICAgYXZnY29lZltpLCBdIDwtIHBhci5hdmcoY2ZhcnJbLCAxTCwgaV0sIGNmYXJyWywgMkwsIGldLCB3ZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRmID0gY2ZhcnJbLCAzTCwgaV0sIGFscGhhID0gYWxwaGEsIHJldmlzZWQudmFyID0gcmV2aXNlZC52YXIpCiAgICAKICAgIGF2Z2NvZWZbaXMubmFuKGF2Z2NvZWYpXSA8LSBOQQogICAgcmV0dXJuKGF2Z2NvZWYpCiAgfQoKLm1ha2Vjb2VmbWF0IDwtIGZ1bmN0aW9uKGNmKSB7CiAgbm8uYXNlIDwtIGFsbChpcy5uYShjZlssIDNMXSkpCiAgeiA8LSBhYnMoY2ZbLCAxTF0gLyBjZlssIGlmKG5vLmFzZSkgMkwgZWxzZSAzTF0pCiAgcHZhbCA8LSAyICogcG5vcm0oeiwgbG93ZXIudGFpbCA9IEZBTFNFKQogIGNiaW5kKGNmWywgaWYobm8uYXNlKSAxTDoyTCBlbHNlIDFMOjNMLCBkcm9wID0gRkFMU0VdLAogICAgICAgIGB6IHZhbHVlYCA9IHosIGBQcig+fHp8KWAgPSB6YXBzbWFsbChwdmFsKSkKfQoKIyBHZW5lcmF0ZSBtb2RlbCBzZWxlY3Rpb25zIHVzaW5nIGxtZXIsIGRyZWRnZSwgYW5kIG1vZGVsLmF2ZwojIGBmb3J1bWxhYCA6IGEgdHdvLXNpZGVkIGxpbmVhciBmb3JtdWxhIG9iamVjdCBkZXNjcmliaW5nIGJvdGggdGhlIGZpeGVkLWVmZmVjdHMgYW5kIHJhbmRvbS1lZmZlY3RzIHBhcnQgb2YgdGhlIG1vZGVsCiMgYGRhdGFgIDogdGhlIGRhdGEgZnJhbWUgY29udGFpbmluZyB0aGUgdmFyaWFibGVzIGZyb20gdGhlIGZvcm11bGEKIyBgYWljX2RlbHRhYCA6IHRoZSBBSUMgZGVsdGEgdG8gdXNlIGZvciBzZWxlY3RpbmcgbW9kZWxzIGluIG1vZGVsIGF2ZXJhZ2UKbW9kZWxfYXZlcmFnZSA8LSBmdW5jdGlvbihmb3JtdWxhLCBkYXRhLCBhaWNfZGVsdGEgPSAyMCkgewogIG1vZGVsIDwtIGxtKAogICAgZm9ybXVsYSwKICAgIGRhdGE9ZGF0YQogICkKICBkcmVkZ2VfcmVzdWx0IDwtIGRyZWRnZShtb2RlbCkKICBzdW1tYXJ5KG1vZGVsLmF2ZyhkcmVkZ2VfcmVzdWx0LCBzdWJzZXQgPSBkZWx0YSA8IGFpY19kZWx0YSkpCn0KCiMgQ3JlYXRlIGEgc3VtbWFyeSBkYXRhIGZyYW1lIGNvbnRhaW5pbmcgdGhlIHNlbGVjdGVkIHZhcmlhYmxlcyBmcm9tIGEgbW9kZWwKIyBgbW9kZWxfc3VtYCA6IFRoZSBtb2RlbCBzdW1tYXJ5IG91dHB1dCBmcm9tIGBtb2RlbF9hdmVyYWdlYAptb2RlbF9zdW1tYXJ5IDwtIGZ1bmN0aW9uKG1vZGVsX3N1bSkgewogIC5jb2x1bW5fbmFtZSA8LSBmdW5jdGlvbihwb3N0Zml4KSB7CiAgICBwb3N0Zml4CiAgfQogIAogICMganVzdCByZXR1cm4gdGhlIGVzdGltYXRlIGFuZCBwIHZhbHVlCiAgd2VpZ2h0IDwtIG1vZGVsX3N1bSRtc1RhYmxlWywgNUxdCiAgCiAgY29lZm1hdC5mdWxsIDwtIGFzLmRhdGEuZnJhbWUoLm1ha2Vjb2VmbWF0KC5jb2VmYXJyLmF2Zyhtb2RlbF9zdW0kY29lZkFycmF5LCB3ZWlnaHQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyKG1vZGVsX3N1bSwgInJldmlzZWQudmFyIiksIFRSVUUsIDAuMDUpKSkKICAKICBjb2VmbWF0LnN1YnNldCA8LQogICAgYXMuZGF0YS5mcmFtZSgubWFrZWNvZWZtYXQoLmNvZWZhcnIuYXZnKG1vZGVsX3N1bSRjb2VmQXJyYXksIHdlaWdodCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyKG1vZGVsX3N1bSwgInJldmlzZWQudmFyIiksIEZBTFNFLCAwLjA1KSkpCiAgCiAgCiAgY29lZm1hdC5zdWJzZXQgPC0gY29lZm1hdC5zdWJzZXRbLWMoMSksIGMoMSwgMiwgNSldCiAgbmFtZXMoY29lZm1hdC5zdWJzZXQpIDwtIGMoLmNvbHVtbl9uYW1lKCJlc3RpbWF0ZSIpLCAuY29sdW1uX25hbWUoImVycm9yIiksIC5jb2x1bW5fbmFtZSgicCIpKQogIGNvZWZtYXQuc3Vic2V0IDwtIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKGNvZWZtYXQuc3Vic2V0LCAiZXhwbGFuYXRvcnkiKQogIGNvZWZtYXQuc3Vic2V0JG1vZGVsID0gJ3N1YnNldCcKICAKICBjb2VmbWF0LmZ1bGwgPC0gY29lZm1hdC5mdWxsWy1jKDEpLCBjKDEsIDIsIDUpXQogIG5hbWVzKGNvZWZtYXQuZnVsbCkgPC0gYyguY29sdW1uX25hbWUoImVzdGltYXRlIiksIC5jb2x1bW5fbmFtZSgiZXJyb3IiKSwgLmNvbHVtbl9uYW1lKCJwIikpCiAgY29lZm1hdC5mdWxsIDwtIHRpYmJsZTo6cm93bmFtZXNfdG9fY29sdW1uKGNvZWZtYXQuZnVsbCwgImV4cGxhbmF0b3J5IikKICBjb2VmbWF0LmZ1bGwkbW9kZWwgPSAnZnVsbCcKICAKICByYmluZChjb2VmbWF0LmZ1bGwsIGNvZWZtYXQuc3Vic2V0KQp9CmBgYAoKYGBge3J9CmZvcm11bGFfZnJvbV92c3VycCA9IGZ1bmN0aW9uKHByZWRpY3RvcnMsIGRlcGVuZGVudCwgdnN1cnBfcmVzdWx0KSB7CiAgYXMuZm9ybXVsYShwYXN0ZShkZXBlbmRlbnQsIHBhc3RlKG5hbWVzKHByZWRpY3RvcnNbLHZzdXJwX3Jlc3VsdCR2YXJzZWxlY3QuaW50ZXJwXSksIGNvbGxhcHNlPSIrIiksIHNlcCA9ICJ+IikpCn0KYGBgCgpgYGB7cn0KcGxvdF92c3VycF9yZXN1bHQgPSBmdW5jdGlvbihyZXN1bHRfdGFibGUpIHsKICBwbG90ID0gcmVzdWx0X3RhYmxlW3Jlc3VsdF90YWJsZSRtb2RlbCA9PSAnZnVsbCcsXQogIHBsb3QgPSB0eXBlX2xhYmVscyhwbG90KQoKICBnZ3Bsb3QocGxvdCwgYWVzKHk9ZXhwbGFuYXRvcnksIHg9ZXN0aW1hdGUsIGNvbG91ciA9IHR5cGUpKSArIAogICAgZ2VvbV9saW5lKCkgKwogICAgZ2VvbV9wb2ludCgpKwogICAgZ2VvbV9lcnJvcmJhcihhZXMoeG1pbj1lc3RpbWF0ZS1lcnJvciwgeG1heD1lc3RpbWF0ZStlcnJvciksIHdpZHRoPS4yLAogICAgICAgICAgICAgICAgICAgcG9zaXRpb249cG9zaXRpb25fZG9kZ2UoMC4wNSkpICsKICAgIHNjYWxlX3lfZGlzY3JldGUoCiAgICAgIGxpbWl0cyA9IHJldihsZXZlbHMocGxvdCRleHBsYW5hdG9yeSkpLCAKICAgICAgbGFiZWxzID0gZXhwbGFuYXRvcnlfbGFiZWxzKSArCiAgICB0aGVtZV9idygpICsKICAgIGdlb21fdmxpbmUoeGludGVyY2VwdD0wLCBsaW5ldHlwZT0iZG90dGVkIikgKwogICAgZ3VpZGVzKGNvbG91cj1ndWlkZV9sZWdlbmQodGl0bGU9IlByZWRpY3RvciB0eXBlIikpICsgeGxhYignSW5jcmVhc2UgZnJvbSAwIChoYWJpdGF0IGZpbHRlcmluZylcbnRvIDEgKGNvbXBldGl0aXZlIGV4Y2x1c2lvbilcbsKxIFN0YW5kYXJkIEVycm9yJykgKyB5bGFiKCdQcmVkaWN0b3InKSArCiAgICB0aGVtZShsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJ0b3AiKQp9CmBgYAoKIyMgTU5URApgYGB7cn0Kbm9ybV9tbnRkX2FuYWx5c2lzX3Bsb3QgPSBnZW9tX25vcm1hbGlzZWRfaGlzdG9ncmFtKAogICdNTlREJywgCiAgZ2dwbG90KGFuYWx5c2lzX2RhdGEsIGFlcyhtbnRkX25vcm1hbGlzZWQpKQopCm5vcm1fbW50ZF9hbmFseXNpc19wbG90CmBgYAoKYGBge3J9Cm5vcm1fbW50ZF9hbmFseXNpc19nZW9fcGxvdCA9IGdlb21fbWFwKGdlb21fc2YoZGF0YSA9IGFuYWx5c2lzX2RhdGEsIGFlcyhjb2xvciA9IG1udGRfbm9ybWFsaXNlZCwgZ2VvbWV0cnkgPSBnZW9tZXRyeSkpLCAnTU5URCcpCm5vcm1fbW50ZF9hbmFseXNpc19nZW9fcGxvdApnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAnbm9ybWFsaXNlZF9tbnRkX3VzaW5nX2FidW5kYW5jZS5qcGcnKSwgd2lkdGggPSAyNTAwLCBoZWlnaHQ9MTEwMCwgdW5pdHMgPSAncHgnKQpgYGAKCmBgYHtyfQpub3JtX21udGRfYW5hbHlzaXNfZGF0YSA9IG1vZGVsX2RhdGEoYW5hbHlzaXNfZGF0YVshaXMubmEoYW5hbHlzaXNfZGF0YSRtbnRkX25vcm1hbGlzZWQpLF0sICdtbnRkX25vcm1hbGlzZWQnKQpub3JtX21udGRfYW5hbHlzaXNfcHJlZGljdG9ycyA9IG5vcm1fbW50ZF9hbmFseXNpc19kYXRhWywtMV0Kbm9ybV9tbnRkX2FuYWx5c2lzX2ludGVycCA9IFZTVVJGKHggPSBub3JtX21udGRfYW5hbHlzaXNfcHJlZGljdG9ycywgeSA9IG5vcm1fbW50ZF9hbmFseXNpc19kYXRhJG1udGRfbm9ybWFsaXNlZCkKbmFtZXMobm9ybV9tbnRkX2FuYWx5c2lzX3ByZWRpY3RvcnNbLG5vcm1fbW50ZF9hbmFseXNpc19pbnRlcnAkdmFyc2VsZWN0LmludGVycF0pCmBgYAoKYGBge3J9Cm5vcm1fbW50ZF9hbmFseXNpc19mb3JtdWxhID0gZm9ybXVsYV9mcm9tX3ZzdXJwKG5vcm1fbW50ZF9hbmFseXNpc19wcmVkaWN0b3JzLCAibW50ZF9ub3JtYWxpc2VkIiwgbm9ybV9tbnRkX2FuYWx5c2lzX2ludGVycCkKbm9ybV9tbnRkX2FuYWx5c2lzX3Jlc3VsdCA8LSBtb2RlbF9hdmVyYWdlKG5vcm1fbW50ZF9hbmFseXNpc19mb3JtdWxhLCBub3JtX21udGRfYW5hbHlzaXNfZGF0YSkKbm9ybV9tbnRkX2FuYWx5c2lzX3Jlc3VsdF90YWJsZSA9IG1vZGVsX3N1bW1hcnkobm9ybV9tbnRkX2FuYWx5c2lzX3Jlc3VsdCkKbm9ybV9tbnRkX2FuYWx5c2lzX3Jlc3VsdF90YWJsZQpgYGAKCmBgYHtyfQpub3JtX21udGRfYW5hbHlzaXNfcHJlZF9wbG90ID0gcGxvdF92c3VycF9yZXN1bHQobm9ybV9tbnRkX2FuYWx5c2lzX3Jlc3VsdF90YWJsZSkKbm9ybV9tbnRkX2FuYWx5c2lzX3ByZWRfcGxvdApgYGAKCiMjIEdhcGUgd2lkdGggLSBGRGl2CmBgYHtyfQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19wbG90ID0gZ2VvbV9ub3JtYWxpc2VkX2hpc3RvZ3JhbSgKICAnR2FwZSBGRGl2JywgCiAgZ2dwbG90KGFuYWx5c2lzX2RhdGEsIGFlcyhnYXBlX3dpZHRoX2ZkaXZfbm9ybWFsaXNlZCkpCikKbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfcGxvdApgYGAKCmBgYHtyfQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19nZW9fcGxvdCA9IGdlb21fbWFwKGdlb21fc2YoZGF0YSA9IGFuYWx5c2lzX2RhdGEsIGFlcyhjb2xvciA9IGdhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkLCBnZW9tZXRyeSA9IGdlb21ldHJ5KSksICdHYXBlIFdpZHRoIEZEaXYnKQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19nZW9fcGxvdApnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAnbm9ybWFsaXNlZF9nYXBlX3dpZHRoX3VzaW5nX2FidW5kYW5jZS5qcGcnKSwgd2lkdGggPSAyNTAwLCBoZWlnaHQ9MTEwMCwgdW5pdHMgPSAncHgnKQpgYGAKCmBgYHtyfQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19kYXRhID0gbW9kZWxfZGF0YShhbmFseXNpc19kYXRhWyFpcy5uYShhbmFseXNpc19kYXRhJGdhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkKSxdLCAnZ2FwZV93aWR0aF9mZGl2X25vcm1hbGlzZWQnKQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19wcmVkaWN0b3JzID0gbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfZGF0YVssLTFdCm5vcm1fZ2FwZV9mZGl2X2FuYWx5c2lzX2ludGVycCA9IFZTVVJGKHggPSBub3JtX2dhcGVfZmRpdl9hbmFseXNpc19wcmVkaWN0b3JzLCB5ID0gbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfZGF0YSRnYXBlX3dpZHRoX2ZkaXZfbm9ybWFsaXNlZCkKbmFtZXMobm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfcHJlZGljdG9yc1ssbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfaW50ZXJwJHZhcnNlbGVjdC5pbnRlcnBdKQpgYGAKCmBgYHtyfQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19mb3JtdWxhID0gZm9ybXVsYV9mcm9tX3ZzdXJwKG5vcm1fZ2FwZV9mZGl2X2FuYWx5c2lzX3ByZWRpY3RvcnMsICJnYXBlX3dpZHRoX2ZkaXZfbm9ybWFsaXNlZCIsIG5vcm1fZ2FwZV9mZGl2X2FuYWx5c2lzX2ludGVycCkKbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfcmVzdWx0IDwtIG1vZGVsX2F2ZXJhZ2Uobm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfZm9ybXVsYSwgbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfZGF0YSkKbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfcmVzdWx0X3RhYmxlID0gbW9kZWxfc3VtbWFyeShub3JtX2dhcGVfZmRpdl9hbmFseXNpc19yZXN1bHQpCm5vcm1fZ2FwZV9mZGl2X2FuYWx5c2lzX3Jlc3VsdF90YWJsZQpgYGAKCmBgYHtyfQpub3JtX2dhcGVfZmRpdl9hbmFseXNpc19wcmVkX3Bsb3QgPSBwbG90X3ZzdXJwX3Jlc3VsdChub3JtX2dhcGVfZmRpdl9hbmFseXNpc19yZXN1bHRfdGFibGUpCm5vcm1fZ2FwZV9mZGl2X2FuYWx5c2lzX3ByZWRfcGxvdApgYGAKCgojIyBIV0kgLSBGRGl2CmBgYHtyfQpub3JtX2h3aV9mZGl2X2xvY29fYW5hbHlzaXNfcGxvdCA9IGdlb21fbm9ybWFsaXNlZF9oaXN0b2dyYW0oCiAgJ0hXSSBGRGl2JywgCiAgZ2dwbG90KGFuYWx5c2lzX2RhdGEsIGFlcyhoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQpKQopCm5vcm1faHdpX2ZkaXZfbG9jb19hbmFseXNpc19wbG90CmBgYAoKYGBge3J9Cm5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfZ2VvX3Bsb3QgPSBnZW9tX21hcChnZW9tX3NmKGRhdGEgPSBhbmFseXNpc19kYXRhLCBhZXMoY29sb3IgPSBoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQsIGdlb21ldHJ5ID0gZ2VvbWV0cnkpKSwgJ0hXSSBGRGl2JykKbm9ybV9od2lfZmRpdl9hbmFseXNpc19nZW9fcGxvdApnZ3NhdmUoZmlsZW5hbWUoRklHVVJFU19PVVRQVVRfRElSLCAnbm9ybWFsaXNlZF9od2lfdXNpbmdfYWJ1bmRhbmNlLmpwZycpLCB3aWR0aCA9IDI1MDAsIGhlaWdodD0xMTAwLCB1bml0cyA9ICdweCcpCmBgYAoKYGBge3J9Cm5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfZGF0YSA9IG1vZGVsX2RhdGEoYW5hbHlzaXNfZGF0YVshaXMubmEoYW5hbHlzaXNfZGF0YSRoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQpLF0sICdoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQnKQpub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3ByZWRpY3RvcnMgPSBub3JtX2h3aV9mZGl2X2FuYWx5c2lzX2RhdGFbLC0xXQpub3JtX2h3aV9mZGl2X2FuYWx5c2lzX2ludGVycCA9IFZTVVJGKHggPSBub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3ByZWRpY3RvcnMsIHkgPSBub3JtX2h3aV9mZGl2X2FuYWx5c2lzX2RhdGEkaGFuZHdpbmdfaW5kZXhfZmRpdl9ub3JtYWxpc2VkKQpuYW1lcyhub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3ByZWRpY3RvcnNbLG5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfaW50ZXJwJHZhcnNlbGVjdC5pbnRlcnBdKQpgYGAKCgpgYGB7cn0Kbm9ybV9od2lfZmRpdl9hbmFseXNpc19mb3JtdWxhID0gZm9ybXVsYV9mcm9tX3ZzdXJwKG5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfcHJlZGljdG9ycywgImhhbmR3aW5nX2luZGV4X2ZkaXZfbm9ybWFsaXNlZCIsIG5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfaW50ZXJwKQpub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3Jlc3VsdCA8LSBtb2RlbF9hdmVyYWdlKG5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfZm9ybXVsYSwgbm9ybV9od2lfZmRpdl9hbmFseXNpc19kYXRhKQpub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3Jlc3VsdF90YWJsZSA9IG1vZGVsX3N1bW1hcnkobm9ybV9od2lfZmRpdl9hbmFseXNpc19yZXN1bHQpCm5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfcmVzdWx0X3RhYmxlCmBgYAoKYGBge3J9Cm5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfcHJlZF9wbG90ID0gcGxvdF92c3VycF9yZXN1bHQobm9ybV9od2lfZmRpdl9hbmFseXNpc19yZXN1bHRfdGFibGUpCm5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfcHJlZF9wbG90CmBgYAoKCiMjIE1hc3MgLSBGRGl2CmBgYHtyfQpub3JtX21hc3NfZmRpdl9sb2NvX2FuYWx5c2lzX3Bsb3QgPSBnZW9tX25vcm1hbGlzZWRfaGlzdG9ncmFtKAogICdNYXNzIEZEaXYnLCAKICBnZ3Bsb3QoYW5hbHlzaXNfZGF0YSwgYWVzKG1hc3NfZmRpdl9ub3JtYWxpc2VkKSkKKQpub3JtX21hc3NfZmRpdl9sb2NvX2FuYWx5c2lzX3Bsb3QKYGBgCgpgYGB7cn0Kbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfZ2VvX3Bsb3QgPSBnZW9tX21hcChnZW9tX3NmKGRhdGEgPSBhbmFseXNpc19kYXRhLCBhZXMoY29sb3IgPSBtYXNzX2ZkaXZfbm9ybWFsaXNlZCwgZ2VvbWV0cnkgPSBnZW9tZXRyeSkpLCAnTWFzcyBGRGl2JykKbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfZ2VvX3Bsb3QKZ2dzYXZlKGZpbGVuYW1lKEZJR1VSRVNfT1VUUFVUX0RJUiwgJ25vcm1hbGlzZWRfbWFzc191c2luZ19hYnVuZGFuY2UuanBnJyksIHdpZHRoID0gMjUwMCwgaGVpZ2h0PTExMDAsIHVuaXRzID0gJ3B4JykKYGBgCgpgYGB7cn0Kbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfZGF0YSA9IG1vZGVsX2RhdGEoYW5hbHlzaXNfZGF0YVshaXMubmEoYW5hbHlzaXNfZGF0YSRtYXNzX2ZkaXZfbm9ybWFsaXNlZCksXSwgJ21hc3NfZmRpdl9ub3JtYWxpc2VkJykKbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfcHJlZGljdG9ycyA9IG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX2RhdGFbLC0xXQpub3JtX21hc3NfZmRpdl9hbmFseXNpc19pbnRlcnAgPSBWU1VSRih4ID0gbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfcHJlZGljdG9ycywgeSA9IG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX2RhdGEkbWFzc19mZGl2X25vcm1hbGlzZWQpCm5hbWVzKG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX3ByZWRpY3RvcnNbLG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX2ludGVycCR2YXJzZWxlY3QuaW50ZXJwXSkKYGBgCgpgYGB7cn0Kbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfZm9ybXVsYSA9IGZvcm11bGFfZnJvbV92c3VycChub3JtX21hc3NfZmRpdl9hbmFseXNpc19wcmVkaWN0b3JzLCAibWFzc19mZGl2X25vcm1hbGlzZWQiLCBub3JtX21hc3NfZmRpdl9hbmFseXNpc19pbnRlcnApCm5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX3Jlc3VsdCA8LSBtb2RlbF9hdmVyYWdlKG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX2Zvcm11bGEsIG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX2RhdGEpCm5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX3Jlc3VsdF90YWJsZSA9IG1vZGVsX3N1bW1hcnkobm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfcmVzdWx0KQpub3JtX21hc3NfZmRpdl9hbmFseXNpc19yZXN1bHRfdGFibGUKYGBgCgpgYGB7cn0Kbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfcHJlZF9wbG90ID0gcGxvdF92c3VycF9yZXN1bHQobm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfcmVzdWx0X3RhYmxlKQpub3JtX21hc3NfZmRpdl9hbmFseXNpc19wcmVkX3Bsb3QKYGBgCiMgQ3JlYXRlIHBsb3Qgb2YgZGlmZmVyZW5jZXMgaW4gcHJvY2VzcyByZXNwb25zZQpgYGB7cn0KcHJlZF9sZWdlbmQgPC0gZ2V0X2xlZ2VuZCgKICAjIGNyZWF0ZSBzb21lIHNwYWNlIHRvIHRoZSBsZWZ0IG9mIHRoZSBsZWdlbmQKICBub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3ByZWRfcGxvdCArIHRoZW1lKGxlZ2VuZC5ib3gubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDEyKSkKKQpnZW9fbGVnZW5kIDwtIGdldF9sZWdlbmQoCiAgIyBjcmVhdGUgc29tZSBzcGFjZSB0byB0aGUgbGVmdCBvZiB0aGUgbGVnZW5kCiAgbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfZ2VvX3Bsb3QgKyB0aGVtZShsZWdlbmQuYm94Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAxMikpCikKCnBsb3RfZ3JpZCgKICBwbG90X2dyaWQoCiAgICBub3JtX21udGRfYW5hbHlzaXNfZ2VvX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgCiAgICBub3JtX21udGRfYW5hbHlzaXNfcHJlZF9wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIAogICAgbnJvdyA9IDEKICApICsgZHJhd19sYWJlbCgiTU5URCIsIHNpemUgPSAxNiwgYW5nbGUgPSA5MCwgeCA9IDAuMDEsIHkgPSAwLjUpLAogIHBsb3RfZ3JpZCgKICAgIG5vcm1fZ2FwZV9mZGl2X2FuYWx5c2lzX2dlb19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIAogICAgbm9ybV9nYXBlX2ZkaXZfYW5hbHlzaXNfcHJlZF9wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIAogICAgbnJvdyA9IDEKICApICsgZHJhd19sYWJlbCgiR2FwZSIsIHNpemUgPSAxNiwgYW5nbGUgPSA5MCwgeCA9IDAuMDEsIHkgPSAwLjUpLAogIHBsb3RfZ3JpZCgKICAgIG5vcm1faHdpX2ZkaXZfYW5hbHlzaXNfZ2VvX3Bsb3QgKyB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSwgCiAgICBub3JtX2h3aV9mZGl2X2FuYWx5c2lzX3ByZWRfcGxvdCArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpLCAKICAgIG5yb3cgPSAxCiAgKSArIGRyYXdfbGFiZWwoIkhXSSIsIHNpemUgPSAxNiwgYW5nbGUgPSA5MCwgeCA9IDAuMDEsIHkgPSAwLjUpLAogIHBsb3RfZ3JpZCgKICAgIG5vcm1fbWFzc19mZGl2X2FuYWx5c2lzX2dlb19wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIAogICAgbm9ybV9tYXNzX2ZkaXZfYW5hbHlzaXNfcHJlZF9wbG90ICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIiksIAogICAgbnJvdyA9IDEKICApICsgZHJhd19sYWJlbCgiTWFzcyIsIHNpemUgPSAxNiwgYW5nbGUgPSA5MCwgeCA9IDAuMDEsIHkgPSAwLjUpLCAKICBwbG90X2dyaWQoCiAgICBnZW9fbGVnZW5kLCAKICAgIHByZWRfbGVnZW5kLCAKICAgIG5yb3cgPSAxCiAgKSwKICBucm93ID0gNQopCmdnc2F2ZShmaWxlbmFtZShGSUdVUkVTX09VVFBVVF9ESVIsICdwcm9jZXNzX3Jlc3BvbnNlLmpwZycpLCB3aWR0aCA9IDI1MDAsIGhlaWdodD01MDAwLCB1bml0cyA9ICdweCcpCmBgYAoKCiMgQ29tcGFyZSBtZXRyaWNzIGFnYWluc3QgZWFjaCBvdGhlcgpgYGB7cn0KZ2dwbG90KGFuYWx5c2lzX2RhdGEsIGFlcyh4ID0gZ2FwZV93aWR0aF9mZGl2X25vcm1hbGlzZWQsIHkgPSBtbnRkX25vcm1hbGlzZWQsIGNvbG91ciA9IGNvcmVfcmVhbG0pKSArIAogIGdlb21fcG9pbnQoKSArCiAgeWxhYigiTU5URCIpICsgCiAgeGxhYigiR2FwZSBXaWR0aCBGRGl2IikgKwogIHRoZW1lX2J3KCkgKyBsYWJzKGNvbG9yID0gIlJlYWxtIikKYGBgCgpgYGB7cn0KZ2dwbG90KGFuYWx5c2lzX2RhdGEsIGFlcyh4ID0gaGFuZHdpbmdfaW5kZXhfZmRpdl9ub3JtYWxpc2VkLCB5ID0gbW50ZF9ub3JtYWxpc2VkLCBjb2xvdXIgPSBjb3JlX3JlYWxtKSkgKyAKICBnZW9tX3BvaW50KCkgKwogIHlsYWIoIk1OVEQiKSArIAogIHhsYWIoIkhXSSBGRGl2IikgKwogIHRoZW1lX2J3KCkgKyBsYWJzKGNvbG9yID0gIlJlYWxtIikKYGBgCgpgYGB7cn0KZ2dwbG90KGFuYWx5c2lzX2RhdGEsIGFlcyh4ID0gaGFuZHdpbmdfaW5kZXhfZmRpdl9ub3JtYWxpc2VkLCB5ID0gZ2FwZV93aWR0aF9mZGl2X25vcm1hbGlzZWQsIGNvbG91ciA9IGNvcmVfcmVhbG0pKSArIAogIGdlb21fcG9pbnQoKSArCiAgeWxhYigiR2FwZSBXaWR0aCBGRGl2IikgKyAKICB4bGFiKCJIV0kgRkRpdiIpICsKICB0aGVtZV9idygpICsgbGFicyhjb2xvciA9ICJSZWFsbSIpCmBgYAoKYGBge3J9Cm1udGRfZmRpdl9hbmFseXNpcyA9IGFuYWx5c2lzX2RhdGEgJT4lIAogIGRwbHlyOjpzZWxlY3QoY2l0eV9pZCwgIG1udGRfbm9ybWFsaXNlZCwgaGFuZHdpbmdfaW5kZXhfZmRpdl9ub3JtYWxpc2VkLCBnYXBlX3dpZHRoX2ZkaXZfbm9ybWFsaXNlZCkgJT4lCiAgbGVmdF9qb2luKGNvbW11bml0eV9zdW1tYXJ5KSAlPiUKICBtdXRhdGUodXJiYW5fcG9vbF9wZXJjID0gdXJiYW5fcG9vbF9zaXplICogMTAwIC8gcmVnaW9uYWxfcG9vbF9zaXplKQptbnRkX2ZkaXZfYW5hbHlzaXMKYGBgCgpgYGB7cn0KZ2dwYWlycyhtbnRkX2ZkaXZfYW5hbHlzaXMgJT4lIGRwbHlyOjpzZWxlY3QobW50ZF9ub3JtYWxpc2VkLCBoYW5kd2luZ19pbmRleF9mZGl2X25vcm1hbGlzZWQsIGdhcGVfd2lkdGhfZmRpdl9ub3JtYWxpc2VkLCByZWdpb25hbF9wb29sX3NpemUsIHVyYmFuX3Bvb2xfc2l6ZSwgdXJiYW5fcG9vbF9wZXJjKSkKZ2dzYXZlKGZpbGVuYW1lKEZJR1VSRVNfT1VUUFVUX0RJUiwgJ2FwcGVuZGl4X25vcm1hbGlzZWRfY29ycmVsYXRpb24uanBnJykpCmBgYAoKCg==